diff options
91 files changed, 5421 insertions, 3392 deletions
| diff --git a/api/current.xml b/api/current.xml index 35fb3ef05a11..b0cb83417fff 100644 --- a/api/current.xml +++ b/api/current.xml @@ -26658,6 +26658,17 @@   visibility="public"  >  </field> +<field name="EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS" + type="java.lang.String" + transient="false" + volatile="false" + value=""extra_click_download_ids"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field>  <field name="PAUSED_QUEUED_FOR_WIFI"   type="int"   transient="false" @@ -27617,6 +27628,17 @@   visibility="public"  >  </method> +<method name="onDestroyOptionsMenu" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method>  <method name="onDestroyView"   return="void"   abstract="false" @@ -83600,6 +83622,17 @@   visibility="public"  >  </method> +<method name="getColor" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method>  <method name="getOpacity"   return="int"   abstract="false" @@ -83624,6 +83657,19 @@  <parameter name="alpha" type="int">  </parameter>  </method> +<method name="setColor" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="color" type="int"> +</parameter> +</method>  <method name="setColorFilter"   return="void"   abstract="false" @@ -145048,6 +145094,23 @@  <parameter name="key" type="java.lang.CharSequence">  </parameter>  </method> +<method name="finishPreferencePanel" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="caller" type="android.app.Fragment"> +</parameter> +<parameter name="resultCode" type="int"> +</parameter> +<parameter name="resultData" type="android.content.Intent"> +</parameter> +</method>  <method name="getPreferenceManager"   return="android.preference.PreferenceManager"   abstract="false" @@ -145276,7 +145339,7 @@  <parameter name="push" type="boolean">  </parameter>  </method> -<method name="startPreferenceFragment" +<method name="startPreferencePanel"   return="void"   abstract="false"   native="false" @@ -145286,9 +145349,17 @@   deprecated="not deprecated"   visibility="public"  > -<parameter name="fragment" type="android.app.Fragment"> +<parameter name="fragmentClass" type="java.lang.String">  </parameter> -<parameter name="ft" type="android.app.FragmentTransaction"> +<parameter name="args" type="android.os.Bundle"> +</parameter> +<parameter name="titleRes" type="int"> +</parameter> +<parameter name="titleText" type="java.lang.CharSequence"> +</parameter> +<parameter name="resultTo" type="android.app.Fragment"> +</parameter> +<parameter name="resultRequestCode" type="int">  </parameter>  </method>  <method name="startWithFragment" @@ -145305,6 +145376,10 @@  </parameter>  <parameter name="args" type="android.os.Bundle">  </parameter> +<parameter name="resultTo" type="android.app.Fragment"> +</parameter> +<parameter name="resultRequestCode" type="int"> +</parameter>  </method>  <method name="switchToHeader"   return="void" @@ -245494,7 +245569,7 @@   deprecated="not deprecated"   visibility="public"  > -<parameter name="t" type="T"> +<parameter name="arg0" type="T">  </parameter>  </method>  </interface> @@ -347567,7 +347642,7 @@   deprecated="not deprecated"   visibility="public"  > -<parameter name="toCopyIn" type="E[]"> +<parameter name="array" type="E[]">  </parameter>  </constructor>  <method name="add" @@ -347595,7 +347670,7 @@  >  <parameter name="index" type="int">  </parameter> -<parameter name="element" type="E"> +<parameter name="e" type="E">  </parameter>  </method>  <method name="addAll" @@ -347723,7 +347798,9 @@   deprecated="not deprecated"   visibility="public"  > -<parameter name="o" type="java.lang.Object"> +<parameter name="e" type="E"> +</parameter> +<parameter name="index" type="int">  </parameter>  </method>  <method name="indexOf" @@ -347736,9 +347813,7 @@   deprecated="not deprecated"   visibility="public"  > -<parameter name="e" type="E"> -</parameter> -<parameter name="index" type="int"> +<parameter name="o" type="java.lang.Object">  </parameter>  </method>  <method name="isEmpty" @@ -347773,7 +347848,9 @@   deprecated="not deprecated"   visibility="public"  > -<parameter name="o" type="java.lang.Object"> +<parameter name="e" type="E"> +</parameter> +<parameter name="index" type="int">  </parameter>  </method>  <method name="lastIndexOf" @@ -347786,9 +347863,7 @@   deprecated="not deprecated"   visibility="public"  > -<parameter name="e" type="E"> -</parameter> -<parameter name="index" type="int"> +<parameter name="o" type="java.lang.Object">  </parameter>  </method>  <method name="listIterator" @@ -347879,7 +347954,7 @@  >  <parameter name="index" type="int">  </parameter> -<parameter name="element" type="E"> +<parameter name="e" type="E">  </parameter>  </method>  <method name="size" diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index 37c8ad0706f5..b5fddfac5eb6 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -389,11 +389,13 @@ public final class Bmgr {              if (err == 0) {                  observer.waitForCompletion();                  sets = observer.sets; -                for (RestoreSet s : sets) { -                    if (s.token == token) { -                        System.out.println("Scheduling restore: " + s.name); -                        didRestore = (mRestore.restoreAll(token, observer) == 0); -                        break; +                if (sets != null) { +                    for (RestoreSet s : sets) { +                        if (s.token == token) { +                            System.out.println("Scheduling restore: " + s.name); +                            didRestore = (mRestore.restoreAll(token, observer) == 0); +                            break; +                        }                      }                  }              } diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java index 1741e60a62be..22424628c47f 100644 --- a/core/java/android/animation/KeyframeSet.java +++ b/core/java/android/animation/KeyframeSet.java @@ -28,12 +28,18 @@ class KeyframeSet {      private int mNumKeyframes; -    ArrayList<Keyframe> mKeyframes; +    Keyframe mFirstKeyframe; +    Keyframe mLastKeyframe; +    TimeInterpolator mInterpolator; // only used in the 2-keyframe case +    ArrayList<Keyframe> mKeyframes; // only used when there are not 2 keyframes      public KeyframeSet(Keyframe... keyframes) { +        mNumKeyframes = keyframes.length;          mKeyframes = new ArrayList<Keyframe>();          mKeyframes.addAll(Arrays.asList(keyframes)); -        mNumKeyframes = mKeyframes.size(); +        mFirstKeyframe = mKeyframes.get(0); +        mLastKeyframe = mKeyframes.get(mNumKeyframes - 1); +        mInterpolator = mLastKeyframe.getInterpolator();      }      public static KeyframeSet ofInt(int... values) { @@ -125,32 +131,40 @@ class KeyframeSet {       * @return The animated value.       */      public Object getValue(float fraction, TypeEvaluator evaluator) { -        // TODO: special-case 2-keyframe common case + +        // Special-case optimization for the common case of only two keyframes +        if (mNumKeyframes == 2) { +            if (mInterpolator != null) { +                fraction = mInterpolator.getInterpolation(fraction); +            } +            return evaluator.evaluate(fraction, mFirstKeyframe.getValue(), +                    mLastKeyframe.getValue()); +        }          if (fraction <= 0f) { -            final Keyframe prevKeyframe = mKeyframes.get(0);              final Keyframe nextKeyframe = mKeyframes.get(1);              final TimeInterpolator interpolator = nextKeyframe.getInterpolator();              if (interpolator != null) {                  fraction = interpolator.getInterpolation(fraction);              } -            float intervalFraction = (fraction - prevKeyframe.getFraction()) / -                (nextKeyframe.getFraction() - prevKeyframe.getFraction()); -            return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(), +            final float prevFraction = mFirstKeyframe.getFraction(); +            float intervalFraction = (fraction - prevFraction) / +                (nextKeyframe.getFraction() - prevFraction); +            return evaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(),                      nextKeyframe.getValue());          } else if (fraction >= 1f) {              final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2); -            final Keyframe nextKeyframe = mKeyframes.get(mNumKeyframes - 1); -            final TimeInterpolator interpolator = nextKeyframe.getInterpolator(); +            final TimeInterpolator interpolator = mLastKeyframe.getInterpolator();              if (interpolator != null) {                  fraction = interpolator.getInterpolation(fraction);              } -            float intervalFraction = (fraction - prevKeyframe.getFraction()) / -                (nextKeyframe.getFraction() - prevKeyframe.getFraction()); +            final float prevFraction = prevKeyframe.getFraction(); +            float intervalFraction = (fraction - prevFraction) / +                (mLastKeyframe.getFraction() - prevFraction);              return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(), -                    nextKeyframe.getValue()); +                    mLastKeyframe.getValue());          } -        Keyframe prevKeyframe = mKeyframes.get(0); +        Keyframe prevKeyframe = mFirstKeyframe;          for (int i = 1; i < mNumKeyframes; ++i) {              Keyframe nextKeyframe = mKeyframes.get(i);              if (fraction < nextKeyframe.getFraction()) { @@ -158,14 +172,15 @@ class KeyframeSet {                  if (interpolator != null) {                      fraction = interpolator.getInterpolation(fraction);                  } -                float intervalFraction = (fraction - prevKeyframe.getFraction()) / -                    (nextKeyframe.getFraction() - prevKeyframe.getFraction()); +                final float prevFraction = prevKeyframe.getFraction(); +                float intervalFraction = (fraction - prevFraction) / +                    (nextKeyframe.getFraction() - prevFraction);                  return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(),                          nextKeyframe.getValue());              }              prevKeyframe = nextKeyframe;          } -        // shouldn't get here -        return mKeyframes.get(mNumKeyframes - 1).getValue(); +        // shouldn't reach here +        return mLastKeyframe.getValue();      }  } diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index 7427651b0923..5b8c91d39e50 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -376,9 +376,14 @@ public final class ObjectAnimator extends ValueAnimator {       */      @Override      public void setTarget(Object target) { -        mTarget = target; -        // New property/values/target should cause re-initialization prior to starting -        mInitialized = false; +        if (mTarget != target) { +            mTarget = target; +            if (mTarget  != null && target != null && mTarget.getClass() == target.getClass()) { +                return; +            } +            // New target type should cause re-initialization prior to starting +            mInitialized = false; +        }      }      @Override diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index ad8c971359f3..a0b70b585adc 100755 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -1142,7 +1142,7 @@ public class ValueAnimator extends Animator {          switch (mPlayingState) {          case RUNNING:          case SEEKED: -            float fraction = (float)(currentTime - mStartTime) / mDuration; +            float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;              if (fraction >= 1f) {                  if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {                      // Time to repeat diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index 66038d8d7919..b359ce6e2905 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java @@ -299,7 +299,7 @@ public abstract class ActionBar {       *        * <p>Example: setDisplayOptions(0, DISPLAY_SHOW_HOME) will disable the       * {@link #DISPLAY_SHOW_HOME} option. -     * setDisplayOptions(DISPLAY_SHOW_HOME, DISPLAY_HIDE_HOME | DISPLAY_USE_LOGO) +     * setDisplayOptions(DISPLAY_SHOW_HOME, DISPLAY_SHOW_HOME | DISPLAY_USE_LOGO)       * will enable {@link #DISPLAY_SHOW_HOME} and disable {@link #DISPLAY_USE_LOGO}.       *        * @param options A combination of the bits defined by the DISPLAY_ constants diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index 45ce86015b88..b9ac84838e65 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -27,6 +27,14 @@ import android.content.res.Configuration;   * AndroidManifest.xml's <application> tag, which will cause that class   * to be instantiated for you when the process for your application/package is   * created. + *  + * <p class="note">There is normally no need to subclass Application.  In + * most situation, static singletons can provide the same functionality in a + * more modular way.  If your singleton needs a global context (for example + * to register broadcast receivers), the function to retrieve it can be + * given a {@link android.content.Context} which internally uses + * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()} + * when first constructing the singleton.</p>   */  public class Application extends ContextWrapper implements ComponentCallbacks { @@ -46,12 +54,10 @@ public class Application extends ContextWrapper implements ComponentCallbacks {      }      /** -     * Called when the application is stopping.  There are no more application -     * objects running and the process will exit.  <em>Note: never depend on -     * this method being called; in many cases an unneeded application process -     * will simply be killed by the kernel without executing any application -     * code.</em> -     * If you override this method, be sure to call super.onTerminate(). +     * This method is for use in emulated process environments.  It will +     * never be called on a production Android device, where processes are +     * removed by simply killing them; no user code (including this callback) +     * is executed when doing so.       */      public void onTerminate() {      } diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index 570e49471ca8..592a63bc5f2c 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -272,6 +272,14 @@ public class DownloadManager {       */      public static final String EXTRA_DOWNLOAD_ID = "extra_download_id"; +    /** +     * When clicks on multiple notifications are received, the following +     * provides an array of download ids corresponding to the download notification that was +     * clicked. It can be retrieved by the receiver of this +     * Intent using {@link android.content.Intent#getLongArrayExtra(String)}. +     */ +    public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids"; +      // this array must contain all public columns      private static final String[] COLUMNS = new String[] {          COLUMN_ID, diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index f27a15e1cd53..eaf1aee6794a 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -1027,6 +1027,16 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener      }      /** +     * Called when this fragment's option menu items are no longer being +     * included in the overall options menu.  Receiving this call means that +     * the menu needed to be rebuilt, but this fragment's items were not +     * included in the newly built menu (its {@link #onCreateOptionsMenu(Menu, MenuInflater)} +     * was not called). +     */ +    public void onDestroyOptionsMenu() { +    } +     +    /**       * This hook is called whenever an item in your options menu is selected.       * The default implementation simply returns false to have the normal       * processing happen (calling the item's Runnable or sending a message to diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java index 22e074756291..e924c1c079bb 100644 --- a/core/java/android/app/FragmentBreadCrumbs.java +++ b/core/java/android/app/FragmentBreadCrumbs.java @@ -16,6 +16,7 @@  package android.app; +import android.animation.LayoutTransition;  import android.app.FragmentManager.BackStackEntry;  import android.content.Context;  import android.util.AttributeSet; @@ -69,6 +70,7 @@ public class FragmentBreadCrumbs extends ViewGroup          addView(mContainer);          a.getFragmentManager().addOnBackStackChangedListener(this);          updateCrumbs(); +        setLayoutTransition(new LayoutTransition());      }      /** diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 45f9325d2add..512ca164e84a 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -268,6 +268,7 @@ final class FragmentManagerImpl implements FragmentManager {      ArrayList<Fragment> mAdded;      ArrayList<Integer> mAvailIndices;      ArrayList<BackStackRecord> mBackStack; +    ArrayList<Fragment> mCreatedMenus;      // Must be accessed while locked.      ArrayList<BackStackRecord> mBackStackIndices; @@ -1325,15 +1326,32 @@ final class FragmentManagerImpl implements FragmentManager {      public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {          boolean show = false; +        ArrayList<Fragment> newMenus = null;          if (mActive != null) {              for (int i=0; i<mAdded.size(); i++) {                  Fragment f = mAdded.get(i);                  if (f != null && !f.mHidden && f.mHasMenu) {                      show = true;                      f.onCreateOptionsMenu(menu, inflater); +                    if (newMenus == null) { +                        newMenus = new ArrayList<Fragment>(); +                    } +                    newMenus.add(f);                  }              }          } +         +        if (mCreatedMenus != null) { +            for (int i=0; i<mCreatedMenus.size(); i++) { +                Fragment f = mCreatedMenus.get(i); +                if (newMenus == null || !newMenus.contains(f)) { +                    f.onDestroyOptionsMenu(); +                } +            } +        } +         +        mCreatedMenus = newMenus; +                  return show;      } diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index 0c8e4d9eb480..138e7f2c7ded 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -773,6 +773,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine                  case CONNECT_HFP_INCOMING:                      transitionTo(mIncomingHandsfree); +                    break;                  case CONNECT_A2DP_INCOMING:                      transitionTo(mIncomingA2dp); diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java index 72ec46955b9f..841c8f43d42f 100644 --- a/core/java/android/content/UriMatcher.java +++ b/core/java/android/content/UriMatcher.java @@ -25,8 +25,8 @@ import java.util.regex.Pattern;  /**  Utility class to aid in matching URIs in content providers. -<p>To use this class, build up a tree of UriMatcher objects. -Typically, it looks something like this: +<p>To use this class, build up a tree of <code>UriMatcher</code> objects. +For example:  <pre>      private static final int PEOPLE = 1;      private static final int PEOPLE_ID = 2; @@ -48,36 +48,35 @@ Typically, it looks something like this:      private static final int CALLS_ID = 12;      private static final int CALLS_FILTER = 15; -    private static final UriMatcher sURIMatcher = new UriMatcher(); +    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);      static      { -        sURIMatcher.addURI("contacts", "/people", PEOPLE); -        sURIMatcher.addURI("contacts", "/people/#", PEOPLE_ID); -        sURIMatcher.addURI("contacts", "/people/#/phones", PEOPLE_PHONES); -        sURIMatcher.addURI("contacts", "/people/#/phones/#", PEOPLE_PHONES_ID); -        sURIMatcher.addURI("contacts", "/people/#/contact_methods", PEOPLE_CONTACTMETHODS); -        sURIMatcher.addURI("contacts", "/people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID); -        sURIMatcher.addURI("contacts", "/deleted_people", DELETED_PEOPLE); -        sURIMatcher.addURI("contacts", "/phones", PHONES); -        sURIMatcher.addURI("contacts", "/phones/filter/*", PHONES_FILTER); -        sURIMatcher.addURI("contacts", "/phones/#", PHONES_ID); -        sURIMatcher.addURI("contacts", "/contact_methods", CONTACTMETHODS); -        sURIMatcher.addURI("contacts", "/contact_methods/#", CONTACTMETHODS_ID); -        sURIMatcher.addURI("call_log", "/calls", CALLS); -        sURIMatcher.addURI("call_log", "/calls/filter/*", CALLS_FILTER); -        sURIMatcher.addURI("call_log", "/calls/#", CALLS_ID); +        sURIMatcher.addURI("contacts", "people", PEOPLE); +        sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID); +        sURIMatcher.addURI("contacts", "people/#/phones", PEOPLE_PHONES); +        sURIMatcher.addURI("contacts", "people/#/phones/#", PEOPLE_PHONES_ID); +        sURIMatcher.addURI("contacts", "people/#/contact_methods", PEOPLE_CONTACTMETHODS); +        sURIMatcher.addURI("contacts", "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID); +        sURIMatcher.addURI("contacts", "deleted_people", DELETED_PEOPLE); +        sURIMatcher.addURI("contacts", "phones", PHONES); +        sURIMatcher.addURI("contacts", "phones/filter/*", PHONES_FILTER); +        sURIMatcher.addURI("contacts", "phones/#", PHONES_ID); +        sURIMatcher.addURI("contacts", "contact_methods", CONTACTMETHODS); +        sURIMatcher.addURI("contacts", "contact_methods/#", CONTACTMETHODS_ID); +        sURIMatcher.addURI("call_log", "calls", CALLS); +        sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER); +        sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);      }  </pre> -<p>Then when you need to match match against a URI, call {@link #match}, providing -the tokenized url you've been given, and the value you want if there isn't -a match.  You can use the result to build a query, return a type, insert or -delete a row, or whatever you need, without duplicating all of the if-else -logic you'd otherwise need.  Like this: +<p>Then when you need to match against a URI, call {@link #match}, providing +the URL that you have been given.  You can use the result to build a query, +return a type, insert or delete a row, or whatever you need, without duplicating +all of the if-else logic that you would otherwise need.  For example:  <pre> -    public String getType(String[] url) +    public String getType(Uri url)      { -        int match = sURIMatcher.match(url, NO_MATCH); +        int match = sURIMatcher.match(url);          switch (match)          {              case PEOPLE: @@ -93,19 +92,20 @@ logic you'd otherwise need.  Like this:          }      }  </pre> -instead of +instead of:  <pre> -    public String getType(String[] url) +    public String getType(Uri url)      { -        if (url.length >= 2) { -            if (url[1].equals("people")) { -                if (url.length == 2) { +        List<String> pathSegments = url.getPathSegments(); +        if (pathSegments.size() >= 2) { +            if ("people".equals(pathSegments.get(1))) { +                if (pathSegments.size() == 2) {                      return "vnd.android.cursor.dir/person"; -                } else if (url.length == 3) { +                } else if (pathSegments.size() == 3) {                      return "vnd.android.cursor.item/person";  ... snip ...                      return "vnd.android.cursor.dir/snail-mail"; -                } else if (url.length == 3) { +                } else if (pathSegments.size() == 3) {                      return "vnd.android.cursor.item/snail-mail";                  }              } diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index 0c6a237061c4..97c957d60ba1 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -825,7 +825,7 @@ public abstract class PreferenceActivity extends ListActivity implements      /**       * Called when the user selects an item in the header list.  The default -     * implementation will call either {@link #startWithFragment(String, Bundle)} +     * implementation will call either {@link #startWithFragment(String, Bundle, Fragment, int)}       * or {@link #switchToHeader(Header)} as appropriate.       *       * @param header The header that was selected. @@ -834,7 +834,7 @@ public abstract class PreferenceActivity extends ListActivity implements      public void onHeaderClick(Header header, int position) {          if (header.fragment != null) {              if (mSinglePane) { -                startWithFragment(header.fragment, header.fragmentArguments); +                startWithFragment(header.fragment, header.fragmentArguments, null, 0);              } else {                  switchToHeader(header);              } @@ -852,13 +852,18 @@ public abstract class PreferenceActivity extends ListActivity implements       * @param fragmentName The name of the fragment to display.       * @param args Optional arguments to supply to the fragment.       */ -    public void startWithFragment(String fragmentName, Bundle args) { +    public void startWithFragment(String fragmentName, Bundle args, +            Fragment resultTo, int resultRequestCode) {          Intent intent = new Intent(Intent.ACTION_MAIN);          intent.setClass(this, getClass());          intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);          intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);          intent.putExtra(EXTRA_NO_HEADERS, true); -        startActivity(intent); +        if (resultTo == null) { +            startActivity(intent); +        } else { +            resultTo.startActivityForResult(intent, resultRequestCode); +        }      }      /** @@ -923,9 +928,15 @@ public abstract class PreferenceActivity extends ListActivity implements       * @param header The new header to display.       */      public void switchToHeader(Header header) { -        int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader); -        switchToHeaderInner(header.fragment, header.fragmentArguments, direction); -        setSelectedHeader(header); +        if (mCurHeader == header) { +            // This is the header we are currently displaying.  Just make sure +            // to pop the stack up to its root state. +            getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE); +        } else { +            int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader); +            switchToHeaderInner(header.fragment, header.fragmentArguments, direction); +            setSelectedHeader(header); +        }      }      Header findBestMatchingHeader(Header cur, ArrayList<Header> from) { @@ -982,7 +993,7 @@ public abstract class PreferenceActivity extends ListActivity implements       */      public void startPreferenceFragment(Fragment fragment, boolean push) {          FragmentTransaction transaction = getFragmentManager().openTransaction(); -        startPreferenceFragment(fragment, transaction); +        transaction.replace(com.android.internal.R.id.prefs, fragment);          if (push) {              transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);              transaction.addToBackStack(BACK_STACK_PREFS); @@ -993,25 +1004,74 @@ public abstract class PreferenceActivity extends ListActivity implements      }      /** -     * Start a new fragment. -     * -     * @param fragment The fragment to start -     * @param ft The FragmentTransaction in which to perform this operation. -     * Will not be added to the back stack or committed for you; you use do that. +     * Start a new fragment containing a preference panel.  If the prefences +     * are being displayed in multi-pane mode, the given fragment class will +     * be instantiated and placed in the appropriate pane.  If running in +     * single-pane mode, a new activity will be launched in which to show the +     * fragment. +     *  +     * @param fragmentClass Full name of the class implementing the fragment. +     * @param args Any desired arguments to supply to the fragment. +     * @param titleRes Optional resource identifier of the title of this +     * fragment. +     * @param titleText Optional text of the title of this fragment. +     * @param resultTo Optional fragment that result data should be sent to. +     * If non-null, resultTo.onActivityResult() will be called when this +     * preference panel is done.  The launched panel must use +     * {@link #finishPreferencePanel(Fragment, int, Intent)} when done. +     * @param resultRequestCode If resultTo is non-null, this is the caller's +     * request code to be received with the resut.       */ -    public void startPreferenceFragment(Fragment fragment, FragmentTransaction ft) { -        ft.replace(com.android.internal.R.id.prefs, fragment); +    public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes, +            CharSequence titleText, Fragment resultTo, int resultRequestCode) { +        if (mSinglePane) { +            startWithFragment(fragmentClass, args, resultTo, resultRequestCode); +        } else { +            Fragment f = Fragment.instantiate(this, fragmentClass, args); +            if (resultTo != null) { +                f.setTargetFragment(resultTo, resultRequestCode); +            } +            FragmentTransaction transaction = getFragmentManager().openTransaction(); +            transaction.replace(com.android.internal.R.id.prefs, f); +            if (titleRes != 0) { +                transaction.setBreadCrumbTitle(titleRes); +            } else if (titleText != null) { +                transaction.setBreadCrumbTitle(titleText); +            } +            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); +            transaction.addToBackStack(BACK_STACK_PREFS); +            transaction.commit(); +        }      } - +     +    /** +     * Called by a preference panel fragment to finish itself. +     *  +     * @param caller The fragment that is asking to be finished. +     * @param resultCode Optional result code to send back to the original +     * launching fragment. +     * @param resultData Optional result data to send back to the original +     * launching fragment. +     */ +    public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) { +        if (mSinglePane) { +            setResult(resultCode, resultData); +            finish(); +        } else { +            if (caller != null) { +                if (caller.getTargetFragment() != null) { +                    caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(), +                            resultCode, resultData); +                } +            } +            // XXX be smarter about popping the stack. +            onBackPressed(); +        } +    } +          @Override      public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { -        Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras()); -        FragmentTransaction transaction = getFragmentManager().openTransaction(); -        startPreferenceFragment(f, transaction); -        transaction.setBreadCrumbTitle(pref.getTitle()); -        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); -        transaction.addToBackStack(BACK_STACK_PREFS); -        transaction.commit(); +        startPreferencePanel(pref.getFragment(), pref.getExtras(), 0, pref.getTitle(), null, 0);          return true;      } diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index 72890120914a..ec8f0310fedb 100644 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -385,11 +385,23 @@ public class BluetoothService extends IBluetooth.Stub {          // Allow 3 seconds for profiles to gracefully disconnect          // TODO: Introduce a callback mechanism so that each profile can notify          // BluetoothService when it is done shutting down +        disconnectDevices(); +          mHandler.sendMessageDelayed(                  mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);          return true;      } +    private synchronized void disconnectDevices() { +        // Disconnect devices handled by BluetoothService. +        for (BluetoothDevice device: getConnectedInputDevices()) { +            disconnectInputDevice(device); +        } + +        for (BluetoothDevice device: getConnectedPanDevices()) { +            disconnectPanDevice(device); +        } +    }      private synchronized void finishDisable(boolean saveSetting) {          if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 87e03cf0c8f6..ab975697bd6f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6296,8 +6296,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility              if (invalidateCache) {                  mPrivateFlags &= ~DRAWING_CACHE_VALID;              } -            final ViewParent p = mParent;              final AttachInfo ai = mAttachInfo; +            final ViewParent p = mParent; +            if (ai != null && ai.mHardwareAccelerated) { +                // fast-track for GL-enabled applications; just invalidate the whole hierarchy +                // with a null dirty rect, which tells the ViewRoot to redraw everything +                p.invalidateChild(this, null); +                return; +            }              if (p != null && ai != null) {                  final Rect r = ai.mTmpInvalRect;                  r.set(0, 0, mRight - mLeft, mBottom - mTop); @@ -6321,7 +6327,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility       */      @ViewDebug.ExportedProperty(category = "drawing")      public boolean isOpaque() { -        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK; +        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK && +                (mAlpha >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);      }      private void computeOpaqueFlags() { @@ -8618,7 +8625,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility       */      @RemotableViewMethod      public void setBackgroundColor(int color) { -        setBackgroundDrawable(new ColorDrawable(color)); +        if (mBGDrawable instanceof ColorDrawable) { +            ((ColorDrawable) mBGDrawable).setColor(color); +        } else { +            setBackgroundDrawable(new ColorDrawable(color)); +        }      }      /** diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index b881bdda73a2..aef13add5197 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2101,6 +2101,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager          final int cr = child.mRight;          final int cb = child.mBottom; +        final boolean childHasIdentityMatrix = child.hasIdentityMatrix(); +          final int flags = mGroupFlags;          if ((flags & FLAG_CLEAR_TRANSFORMATION) == FLAG_CLEAR_TRANSFORMATION) { @@ -2182,7 +2184,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager              }          } -        concatMatrix |= !child.hasIdentityMatrix(); +        concatMatrix |= !childHasIdentityMatrix;          // Sets the flag as early as possible to allow draw() implementations          // to call invalidate() successfully when doing animations @@ -2231,40 +2233,41 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager          }          if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) { -            int transX = 0; -            int transY = 0; - -            if (hasNoCache) { -                transX = -sx; -                transY = -sy; -            } +            if (transformToApply != null || !childHasIdentityMatrix) { +                int transX = 0; +                int transY = 0; -            if (transformToApply != null) { -                if (concatMatrix) { -                    // Undo the scroll translation, apply the transformation matrix, -                    // then redo the scroll translate to get the correct result. -                    canvas.translate(-transX, -transY); -                    canvas.concat(transformToApply.getMatrix()); -                    canvas.translate(transX, transY); -                    mGroupFlags |= FLAG_CLEAR_TRANSFORMATION; +                if (hasNoCache) { +                    transX = -sx; +                    transY = -sy;                  } -                float transformAlpha = transformToApply.getAlpha(); -                if (transformAlpha < 1.0f) { -                    alpha *= transformToApply.getAlpha(); -                    mGroupFlags |= FLAG_CLEAR_TRANSFORMATION; +                if (transformToApply != null) { +                    if (concatMatrix) { +                        // Undo the scroll translation, apply the transformation matrix, +                        // then redo the scroll translate to get the correct result. +                        canvas.translate(-transX, -transY); +                        canvas.concat(transformToApply.getMatrix()); +                        canvas.translate(transX, transY); +                        mGroupFlags |= FLAG_CLEAR_TRANSFORMATION; +                    } + +                    float transformAlpha = transformToApply.getAlpha(); +                    if (transformAlpha < 1.0f) { +                        alpha *= transformToApply.getAlpha(); +                        mGroupFlags |= FLAG_CLEAR_TRANSFORMATION; +                    }                  } -            } -            if (!child.hasIdentityMatrix()) { -                canvas.translate(-transX, -transY); -                canvas.concat(child.getMatrix()); -                canvas.translate(transX, transY); +                if (!childHasIdentityMatrix) { +                    canvas.translate(-transX, -transY); +                    canvas.concat(child.getMatrix()); +                    canvas.translate(transX, transY); +                }              }              if (alpha < 1.0f) {                  mGroupFlags |= FLAG_CLEAR_TRANSFORMATION; -                  if (hasNoCache) {                      final int multipliedAlpha = (int) (255 * alpha);                      if (!child.onSetAlpha(multipliedAlpha)) { @@ -3209,19 +3212,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager          final AttachInfo attachInfo = mAttachInfo;          if (attachInfo != null) { -            final int[] location = attachInfo.mInvalidateChildLocation; -            location[CHILD_LEFT_INDEX] = child.mLeft; -            location[CHILD_TOP_INDEX] = child.mTop; -            Matrix childMatrix = child.getMatrix(); -            if (!childMatrix.isIdentity()) { -                RectF boundingRect = attachInfo.mTmpTransformRect; -                boundingRect.set(dirty); -                childMatrix.mapRect(boundingRect); -                dirty.set((int) boundingRect.left, (int) boundingRect.top, -                        (int) (boundingRect.right + 0.5f), -                        (int) (boundingRect.bottom + 0.5f)); -            } -              // If the child is drawing an animation, we want to copy this flag onto              // ourselves and the parent to make sure the invalidate request goes              // through @@ -3229,45 +3219,95 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager              // Check whether the child that requests the invalidate is fully opaque              final boolean isOpaque = child.isOpaque() && !drawAnimation && -                    child.getAnimation() != null; +                    child.getAnimation() == null;              // Mark the child as dirty, using the appropriate flag              // Make sure we do not set both flags at the same time              final int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY; -            do { -                View view = null; -                if (parent instanceof View) { -                    view = (View) parent; -                } +            if (dirty == null) { +                do { +                    View view = null; +                    if (parent instanceof View) { +                        view = (View) parent; +                        if ((view.mPrivateFlags & DIRTY_MASK) != 0) { +                            // already marked dirty - we're done +                            break; +                        } +                    } -                if (drawAnimation) { -                    if (view != null) { -                        view.mPrivateFlags |= DRAW_ANIMATION; -                    } else if (parent instanceof ViewRoot) { -                        ((ViewRoot) parent).mIsAnimating = true; +                    if (drawAnimation) { +                        if (view != null) { +                            view.mPrivateFlags |= DRAW_ANIMATION; +                        } else if (parent instanceof ViewRoot) { +                            ((ViewRoot) parent).mIsAnimating = true; +                        }                      } -                } -                // If the parent is dirty opaque or not dirty, mark it dirty with the opaque -                // flag coming from the child that initiated the invalidate -                if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) { -                    view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag; +                    if (parent instanceof ViewRoot) { +                        ((ViewRoot) parent).invalidate(); +                        parent = null; +                    } else if (view != null) { +                        if ((mPrivateFlags & DRAWN) == DRAWN) { +                            view.mPrivateFlags &= ~DRAWING_CACHE_VALID; +                            if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) { +                                view.mPrivateFlags = +                                        (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag; +                            } +                            parent = view.mParent; +                        } else { +                            parent = null; +                        } +                    } +                } while (parent != null); +            } else { +                final int[] location = attachInfo.mInvalidateChildLocation; +                location[CHILD_LEFT_INDEX] = child.mLeft; +                location[CHILD_TOP_INDEX] = child.mTop; +                Matrix childMatrix = child.getMatrix(); +                if (!childMatrix.isIdentity()) { +                    RectF boundingRect = attachInfo.mTmpTransformRect; +                    boundingRect.set(dirty); +                    childMatrix.mapRect(boundingRect); +                    dirty.set((int) boundingRect.left, (int) boundingRect.top, +                            (int) (boundingRect.right + 0.5f), +                            (int) (boundingRect.bottom + 0.5f));                  } -                parent = parent.invalidateChildInParent(location, dirty); -                if (view != null) { -                    // Account for transform on current parent -                    Matrix m = view.getMatrix(); -                    if (!m.isIdentity()) { -                        RectF boundingRect = attachInfo.mTmpTransformRect; -                        boundingRect.set(dirty); -                        m.mapRect(boundingRect); -                        dirty.set((int) boundingRect.left, (int) boundingRect.top, -                                (int) (boundingRect.right + 0.5f), -                                (int) (boundingRect.bottom + 0.5f)); +                do { +                    View view = null; +                    if (parent instanceof View) { +                        view = (View) parent;                      } -                } -            } while (parent != null); + +                    if (drawAnimation) { +                        if (view != null) { +                            view.mPrivateFlags |= DRAW_ANIMATION; +                        } else if (parent instanceof ViewRoot) { +                            ((ViewRoot) parent).mIsAnimating = true; +                        } +                    } + +                    // If the parent is dirty opaque or not dirty, mark it dirty with the opaque +                    // flag coming from the child that initiated the invalidate +                    if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) { +                        view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag; +                    } + +                    parent = parent.invalidateChildInParent(location, dirty); +                    if (view != null) { +                        // Account for transform on current parent +                        Matrix m = view.getMatrix(); +                        if (!m.isIdentity()) { +                            RectF boundingRect = attachInfo.mTmpTransformRect; +                            boundingRect.set(dirty); +                            m.mapRect(boundingRect); +                            dirty.set((int) boundingRect.left, (int) boundingRect.top, +                                    (int) (boundingRect.right + 0.5f), +                                    (int) (boundingRect.bottom + 0.5f)); +                        } +                    } +                } while (parent != null); +            }          }      } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 06261bb03aaf..22a7773fd1e1 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -543,6 +543,11 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn      public void invalidateChild(View child, Rect dirty) {          checkThread();          if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty); +        if (dirty == null) { +            // Fast invalidation for GL-enabled applications; GL must redraw everything +            invalidate(); +            return; +        }          if (mCurScrollY != 0 || mTranslator != null) {              mTempRect.set(dirty);              dirty = mTempRect; diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index e5f4b087e6fe..c657a1c7908f 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -794,7 +794,17 @@ public interface WindowManager extends ViewManager {          public int softInputMode;          /** -         * Placement of window within the screen as per {@link Gravity} +         * Placement of window within the screen as per {@link Gravity}.  Both +         * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int, +         * android.graphics.Rect) Gravity.apply} and +         * {@link Gravity#applyDisplay(int, android.graphics.Rect, android.graphics.Rect) +         * Gravity.applyDisplay} are used during window layout, with this value +         * given as the desired gravity.  For example you can specify +         * {@link Gravity#DISPLAY_CLIP_HORIZONTAL Gravity.DISPLAY_CLIP_HORIZONTAL} and +         * {@link Gravity#DISPLAY_CLIP_VERTICAL Gravity.DISPLAY_CLIP_VERTICAL} here +         * to control the behavior of +         * {@link Gravity#applyDisplay(int, android.graphics.Rect, android.graphics.Rect) +         * Gravity.applyDisplay}.           *           * @see Gravity           */ @@ -802,13 +812,19 @@ public interface WindowManager extends ViewManager {          /**           * The horizontal margin, as a percentage of the container's width, -         * between the container and the widget. +         * between the container and the widget.  See +         * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int, +         * android.graphics.Rect) Gravity.apply} for how this is used.  This +         * field is added with {@link #x} to supply the <var>xAdj</var> parameter.           */          public float horizontalMargin;          /**           * The vertical margin, as a percentage of the container's height, -         * between the container and the widget. +         * between the container and the widget.  See +         * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int, +         * android.graphics.Rect) Gravity.apply} for how this is used.  This +         * field is added with {@link #y} to supply the <var>yAdj</var> parameter.           */          public float verticalMargin; @@ -1168,14 +1184,22 @@ public interface WindowManager extends ViewManager {              sb.append('x');              sb.append((height== MATCH_PARENT ?"fill":(height==WRAP_CONTENT?"wrap":height)));              sb.append(")"); -            if (softInputMode != 0) { -                sb.append(" sim=#"); -                sb.append(Integer.toHexString(softInputMode)); +            if (horizontalMargin != 0) { +                sb.append(" hm="); +                sb.append(horizontalMargin); +            } +            if (verticalMargin != 0) { +                sb.append(" vm="); +                sb.append(verticalMargin);              }              if (gravity != 0) {                  sb.append(" gr=#");                  sb.append(Integer.toHexString(gravity));              } +            if (softInputMode != 0) { +                sb.append(" sim=#"); +                sb.append(Integer.toHexString(softInputMode)); +            }              sb.append(" ty=");              sb.append(type);              sb.append(" fl=#"); @@ -1190,6 +1214,18 @@ public interface WindowManager extends ViewManager {                  sb.append(" or=");                  sb.append(screenOrientation);              } +            if (alpha != 1.0f) { +                sb.append(" alpha="); +                sb.append(alpha); +            } +            if (screenBrightness != BRIGHTNESS_OVERRIDE_NONE) { +                sb.append(" sbrt="); +                sb.append(screenBrightness); +            } +            if (buttonBrightness != BRIGHTNESS_OVERRIDE_NONE) { +                sb.append(" bbrt="); +                sb.append(buttonBrightness); +            }              if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) {                  sb.append(" compatible=true");              } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 1fd31a3ac33e..1a341e11d8b8 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -544,16 +544,18 @@ public interface WindowManagerPolicy {       * Generally, it's best to keep as little as possible in the queue thread       * because it's the most fragile.       * @param whenNanos The event time in uptime nanoseconds. +     * @param action The key event action. +     * @param flags The key event flags.       * @param keyCode The key code. -     * @param down True if the key is down. +     * @param scanCode The key's scan code.       * @param policyFlags The policy flags associated with the key.       * @param isScreenOn True if the screen is already on       *       * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},       *          {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.       */ -    public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, int policyFlags, -            boolean isScreenOn); +    public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, +            int keyCode, int scanCode, int policyFlags, boolean isScreenOn);      /**       * Called from the input dispatcher thread before a key is dispatched to a window. @@ -571,6 +573,7 @@ public interface WindowManagerPolicy {       * @param action The key event action.       * @param flags The key event flags.       * @param keyCode The key code. +     * @param scanCode The key's scan code.       * @param metaState bit mask of meta keys that are held.       * @param repeatCount Number of times a key down has repeated.       * @param policyFlags The policy flags associated with the key. @@ -578,7 +581,7 @@ public interface WindowManagerPolicy {       * not be further dispatched.       */      public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, -            int keyCode, int metaState, int repeatCount, int policyFlags); +            int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags);      /**       * Called when layout of the windows is about to start. diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 3bcd483a4cc3..14dc61d6e7cd 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -370,6 +370,7 @@ import java.util.ArrayList;              int candEnd = EditableInputConnection.getComposingSpanEnd(sp);              imm.updateSelection(this, selStart, selEnd, candStart, candEnd);          } +        updateCursorControllerPositions();      }      @Override diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 72b4e360305a..f5affe588180 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -3477,7 +3477,9 @@ public class WebView extends AbsoluteLayout          if (AUTO_REDRAW_HACK && mAutoRedraw) {              invalidate();          } -        if (inEditingMode()) mWebTextView.onDrawSubstitute(); +        if (inEditingMode()) { +            mWebTextView.onDrawSubstitute(); +        }          mWebViewCore.signalRepaintDone();          // paint the highlight in the end diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 39b1377c1e68..be1234d9256d 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -413,33 +413,46 @@ public class MediaController extends FrameLayout {      @Override      public boolean dispatchKeyEvent(KeyEvent event) {          int keyCode = event.getKeyCode(); -        if (event.getRepeatCount() == 0 && event.isDown() && ( -                keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK || -                keyCode ==  KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || -                keyCode ==  KeyEvent.KEYCODE_SPACE)) { -            doPauseResume(); -            show(sDefaultTimeout); -            if (mPauseButton != null) { -                mPauseButton.requestFocus(); +        final boolean uniqueDown = event.getRepeatCount() == 0 +                && event.getAction() == KeyEvent.ACTION_DOWN; +        if (keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK +                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE +                || keyCode == KeyEvent.KEYCODE_SPACE) { +            if (uniqueDown) { +                doPauseResume(); +                show(sDefaultTimeout); +                if (mPauseButton != null) { +                    mPauseButton.requestFocus(); +                } +            } +            return true; +        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { +            if (uniqueDown && !mPlayer.isPlaying()) { +                mPlayer.start(); +                updatePausePlay(); +                show(sDefaultTimeout);              }              return true; -        } else if (keyCode ==  KeyEvent.KEYCODE_MEDIA_STOP) { -            if (mPlayer.isPlaying()) { +        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP +                || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { +            if (uniqueDown && mPlayer.isPlaying()) {                  mPlayer.pause();                  updatePausePlay(); +                show(sDefaultTimeout);              }              return true; -        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || -                keyCode == KeyEvent.KEYCODE_VOLUME_UP) { +        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN +                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {              // don't show the controls for volume adjustment              return super.dispatchKeyEvent(event);          } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) { -            hide(); - +            if (uniqueDown) { +                hide(); +            }              return true; -        } else { -            show(sDefaultTimeout);          } + +        show(sDefaultTimeout);          return super.dispatchKeyEvent(event);      } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 35c50fd52e03..6ba7b44fe1eb 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -132,6 +132,25 @@ public class RemoteViews implements Parcelable, Filter {              // here              return;          } + +        protected boolean startIntentSafely(Context context, PendingIntent pendingIntent, +                Intent fillInIntent) { +            try { +                // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? +                context.startIntentSender( +                        pendingIntent.getIntentSender(), fillInIntent, +                        Intent.FLAG_ACTIVITY_NEW_TASK, +                        Intent.FLAG_ACTIVITY_NEW_TASK, 0); +            } catch (IntentSender.SendIntentException e) { +                android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e); +                return false; +            } catch (Exception e) { +                android.util.Log.e(LOG_TAG, "Cannot send pending intent due to " + +                        "unknown exception: ", e); +                return false; +            } +            return true; +        }      }      private class SetEmptyView extends Action { @@ -236,15 +255,7 @@ public class RemoteViews implements Parcelable, Filter {                          rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);                          fillInIntent.setSourceBounds(rect); -                        try { -                            // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? -                            v.getContext().startIntentSender( -                                    pendingIntent.getIntentSender(), fillInIntent, -                                    Intent.FLAG_ACTIVITY_NEW_TASK, -                                    Intent.FLAG_ACTIVITY_NEW_TASK, 0); -                        } catch (IntentSender.SendIntentException e) { -                            android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e); -                        } +                        startIntentSafely(v.getContext(), pendingIntent, fillInIntent);                      }                  }; @@ -326,16 +337,7 @@ public class RemoteViews implements Parcelable, Filter {                          final Intent intent = new Intent();                          intent.setSourceBounds(rect);                          intent.putExtras(extras); - -                        try { -                            // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? -                            v.getContext().startIntentSender( -                                    pendingIntent.getIntentSender(), intent, -                                    Intent.FLAG_ACTIVITY_NEW_TASK, -                                    Intent.FLAG_ACTIVITY_NEW_TASK, 0); -                        } catch (IntentSender.SendIntentException e) { -                            android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e); -                        } +                        startIntentSafely(v.getContext(), pendingIntent, intent);                      }                  }; @@ -441,15 +443,7 @@ public class RemoteViews implements Parcelable, Filter {                          final Intent intent = new Intent();                          intent.setSourceBounds(rect); -                        try { -                            // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? -                            v.getContext().startIntentSender( -                                    pendingIntent.getIntentSender(), intent, -                                    Intent.FLAG_ACTIVITY_NEW_TASK, -                                    Intent.FLAG_ACTIVITY_NEW_TASK, 0); -                        } catch (IntentSender.SendIntentException e) { -                            android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e); -                        } +                        startIntentSafely(v.getContext(), pendingIntent, intent);                      }                  };                  target.setOnClickListener(listener); diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index 36adacdf2620..ce4e8e5230d0 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -115,7 +115,6 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {      }      private void initTabWidget() { -        setOrientation(LinearLayout.HORIZONTAL);          mGroupFlags |= FLAG_USE_CHILD_DRAWING_ORDER;          final Context context = mContext; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 9855d6e5d247..2fcae1cb3eeb 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4277,6 +4277,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener          canvas.restore(); +        updateCursorControllerPositions(); +    } + +    /** +     * Update the positions of the CursorControllers.  Needed by WebTextView, +     * which does not draw. +     * @hide +     */ +    protected void updateCursorControllerPositions() {          if (mInsertionPointCursorController != null &&                  mInsertionPointCursorController.isShowing()) {              mInsertionPointCursorController.updatePosition(); diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 3d9cde4e9749..2be7bcaa87e8 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -529,10 +529,19 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {                      mMediaController.hide();                  }                  return true; +            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { +                if (mMediaPlayer.isPlaying()) { +                    start(); +                    mMediaController.hide(); +                } +                return true;              } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP -                    && mMediaPlayer.isPlaying()) { -                pause(); -                mMediaController.show(); +                    || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { +                if (!mMediaPlayer.isPlaying()) { +                    pause(); +                    mMediaController.show(); +                } +                return true;              } else {                  toggleMediaControlsVisiblity();              } diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java index b87ac908da0e..6d2bcae4f194 100644 --- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java +++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java @@ -82,8 +82,8 @@ public class SamplingProfilerIntegration {          }          ThreadGroup group = Thread.currentThread().getThreadGroup();          SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupTheadSet(group); -        INSTANCE = new SamplingProfiler(4, threadSet); -        INSTANCE.start(samplingProfilerHz); +        INSTANCE = new SamplingProfiler(4, threadSet); // TODO parameter for depth +        INSTANCE.start(1000/samplingProfilerHz);      }      /** diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml index 7a9a3b909e37..edf194843b9e 100644 --- a/core/res/res/anim/fragment_close_enter.xml +++ b/core/res/res/anim/fragment_close_enter.xml @@ -26,7 +26,7 @@          android:duration="@android:integer/config_mediumAnimTime"/>      <objectAnimator          android:interpolator="@anim/decelerate_interpolator" -        android:valueFrom="-400" +        android:valueFrom="-100"          android:valueTo="0"          android:valueType="floatType"          android:propertyName="translationX" diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml index 07435776aac6..fbba47614e85 100644 --- a/core/res/res/anim/fragment_close_exit.xml +++ b/core/res/res/anim/fragment_close_exit.xml @@ -27,7 +27,7 @@      <objectAnimator          android:interpolator="@anim/accelerate_interpolator"          android:valueFrom="0" -        android:valueTo="400" +        android:valueTo="100"          android:valueType="floatType"          android:propertyName="translationX"          android:duration="@android:integer/config_mediumAnimTime"/> diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml index ac6049465373..334f4ef6f93d 100644 --- a/core/res/res/anim/fragment_open_enter.xml +++ b/core/res/res/anim/fragment_open_enter.xml @@ -24,7 +24,7 @@          android:propertyName="alpha"          android:duration="@android:integer/config_mediumAnimTime"/>      <objectAnimator -        android:valueFrom="400" +        android:valueFrom="100"          android:valueTo="0"          android:valueType="floatType"          android:propertyName="translationX" diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml index 3bf1ad491a08..764fc3987e44 100644 --- a/core/res/res/anim/fragment_open_exit.xml +++ b/core/res/res/anim/fragment_open_exit.xml @@ -25,7 +25,7 @@          android:duration="@android:integer/config_mediumAnimTime"/>      <objectAnimator          android:valueFrom="0" -        android:valueTo="-400" +        android:valueTo="-100"          android:valueType="floatType"          android:propertyName="translationX"          android:duration="@android:integer/config_mediumAnimTime"/> diff --git a/core/res/res/layout/tab_content.xml b/core/res/res/layout/tab_content.xml index 0ee87cebbfc2..79147fbe3845 100644 --- a/core/res/res/layout/tab_content.xml +++ b/core/res/res/layout/tab_content.xml @@ -22,8 +22,9 @@  	android:layout_width="match_parent" android:layout_height="match_parent">  	<LinearLayout android:orientation="vertical"      	android:layout_width="match_parent" android:layout_height="match_parent"> -        <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" -        	android:layout_height="wrap_content" android:layout_weight="0" /> +    <TabWidget android:id="@android:id/tabs" +        android:orientation="horizontal" android:layout_width="match_parent" +        android:layout_height="wrap_content" android:layout_weight="0" />          <FrameLayout android:id="@android:id/tabcontent"          	android:layout_width="match_parent" android:layout_height="0dip"              android:layout_weight="1"/> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 077ce267d30d..80072f42471a 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -572,7 +572,7 @@      <style name="Theme.IconMenu">          <!-- Menu/item attributes -->          <item name="android:itemTextAppearance">@android:style/TextAppearance.Widget.IconMenu.Item</item> -        <item name="android:selectableItemBackground">@android:drawable/menu_selector</item> +        <item name="android:itemBackground">@android:drawable/menu_selector</item>          <item name="android:itemIconDisabledAlpha">?android:attr/disabledAlpha</item>          <item name="android:horizontalDivider">@android:drawable/divider_horizontal_dark</item>          <item name="android:verticalDivider">@android:drawable/divider_vertical_dark</item> diff --git a/docs/html/guide/developing/tools/MonkeyDevice.jd b/docs/html/guide/developing/tools/MonkeyDevice.jd new file mode 100644 index 000000000000..34bbba95a8e3 --- /dev/null +++ b/docs/html/guide/developing/tools/MonkeyDevice.jd @@ -0,0 +1,1353 @@ +page.title=MonkeyDevice +@jd:body +<style> +    h4.jd-details-title {background-color: #DEE8F1;} +</style> +<p> +    A monkeyrunner class that represents a device or emulator accessible by the workstation running +<code><a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a></code>. +</p> +<p> +    This class is used to control an Android device or emulator. The methods send UI events, +    retrieve information, install and remove applications, and run applications. +</p> +<p> +    You normally do not have to create an instance of <code>MonkeyDevice</code>. Instead, you +    use +<code><a href="{@docRoot}guide/developing/tools/MonkeyRunner.html#waitForConnection"> +MonkeyRunner.waitForConnection()</a></code> to create a new object from a connection to a device or +emulator. For example, instead of +using:</p> +<pre> +newdevice = MonkeyDevice() +</pre> +<p> +    you would use: +</p> +<pre> +newdevice = MonkeyRunner.waitForConnection() +</pre> +<h2>Summary</h2> +    <table id="constants" class="jd-sumtable" style="background-color: white;"> +       <tr> +            <th colspan="12" style="background-color: #E2E2E2">Constants</th> +       </tr> +        <tr class="api" style="background-color: white;"> +            <td class="jd-typecol"><em>string</em></td> +            <td class="jd-linkcol"><a href="#ACTION_DOWN">DOWN</a></td> +            <td class="jd-descrcol" width="100%"> +                Use this with the <code>type</code> argument of +                <code><a href="#press">press()</a></code> or <code><a href="#touch">touch()</a> +                </code> +                to send a DOWN event. +            </td> +        </tr> +        <tr class="api" style="background-color: white;"> +            <td class="jd-typecol"><em>string</em></td> +            <td class="jd-linkcol"><a href="#ACTION_UP">UP</a></td> +            <td class="jd-descrcol" width="100%"> +                Use this with the <code>type</code> argument of +                <code><a href="#press">press()</a></code> or <code><a href="#touch">touch()</a> +                </code> +                to send an UP event. +            </td> +        </tr> +        <tr class="api" style="background-color: white;"> +            <td class="jd-typecol"><em>string</em></td> +            <td class="jd-linkcol"><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></td> +            <td class="jd-descrcol" width="100%"> +                Use this with the <code>type</code> argument of +                <code><a href="#press">press()</a></code> or <code><a href="#touch">touch()</a> +                </code> +                to send a DOWN event immediately followed by an UP event. +            </td> +        </tr> +    </table> +<table id="pubmethods" class="jd-sumtable"> +    <tr> +        <th colspan="12" style="background-color: #E2E2E2">Methods</th> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#broadcastIntent">broadcastIntent</a> +                </span> +                (<em>string</em> uri, +                <em>string</em> action, +                <em>string</em> data, +                <em>string</em> mimetype, +                <em>iterable</em> categories +                <em>dictionary</em> extras, +                <em>component</em> component, +                <em>iterable</em> flags) +            </nobr> +            <div class="jd-descrdiv"> +                Broadcasts an Intent to this device, as if the Intent were coming from an +                application. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#drag">drag</a> +                </span> +                (<em>tuple</em> start, +                <em>tuple</em> end, +                <em>float</em> duration, +                <em>integer</em> steps) +            </nobr> +            <div class="jd-descrdiv"> +                Simulates a drag gesture (touch, hold, and move) on this device's screen. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>object</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#getProperty">getProperty</a> +                </span> +                (<em>string</em> key) +            </nobr> +            <div class="jd-descrdiv"> +                Given the name of a system environment variable, returns its value for this device. +                The available variable names are listed in the <a href="#getProperty"> +                detailed description</a> of this method. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>object</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#getSystemProperty">getSystemProperty</a> +                </span> +                (<em>string</em> key) +            </nobr> +            <div class="jd-descrdiv"> +.               The API equivalent of <code>adb shell getprop <key>. This is provided for use +                by platform developers. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#installPackage">installPackage</a> +                </span> +                (<em>string</em> path) +            </nobr> +            <div class="jd-descrdiv"> +                Installs the Android application or test package contained in packageFile onto this +                device. If the application or test package is already installed, it is replaced. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>dictionary</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#instrument">instrument</a> +                </span> +                (<em>string</em> className, +                <em>dictionary</em> args) +            </nobr> +            <div class="jd-descrdiv"> +                Runs the specified component under Android instrumentation, and returns the results +                in a dictionary whose exact format is dictated by the component being run. The +                component must already be present on this device. +            </div> +        </td> +    </tr> +    <tr class="api"> +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#press">press</a> +                </span> +                (<em>string</em> name, +                <em>dictionary</em> type) +            </nobr> +            <div class="jd-descrdiv"> +                Sends the key event specified by type to the key specified by +                keycode. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#reboot">reboot</a> +                </span> +                (<em>string</em> into) +            </nobr> +            <div class="jd-descrdiv"> +                Reboots this device into the bootloader specified by bootloadType. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#removePackage">removePackage</a> +                </span> +                (<em>string</em> package) +            </nobr> +            <div class="jd-descrdiv"> +                Deletes the specified package from this device, including its data and cache. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>object</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#shell">shell</a> +                </span> +                (<em>string</em> cmd) +            </nobr> +            <div class="jd-descrdiv"> +                Executes an <code>adb</code> shell command and returns the result, if any. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#startActivity">startActivity</a> +                </span> +                (<em>string</em> uri, +                <em>string</em> action, +                <em>string</em> data, +                <em>string</em> mimetype, +                <em>iterable</em> categories +                <em>dictionary</em> extras, +                <em>component</em> component, +                <em>flags</em>) +            </nobr> +            <div class="jd-descrdiv"> +                Starts an Activity on this device by sending an Intent constructed from the +                supplied arguments. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <code> +                <a href="{@docRoot}guide/developing/tools/MonkeyImage.html"> +                        MonkeyImage +                    </a> +                </code> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#takeSnapshot">takeSnapshot</a>() +                </span> +            </nobr> +            <div class="jd-descrdiv"> +                Captures the entire screen buffer of this device, yielding a +                <code> +                <a href="{@docRoot}guide/developing/tools/MonkeyImage.html"> +                        MonkeyImage +                </a> +                </code> object containing a screen capture of the current display. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#touch">touch</a> +                </span> +               (<em>integer</em> x, +                 <em>integer</em> y, +                 <em>integer</em> type) +            </nobr> +            <div class="jd-descrdiv"> +                Sends a touch event specified by type to the screen location specified +                by x and y. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#touch">type</a> +                </span> +                   (<em>string</em> message) +            </nobr> +            <div class="jd-descrdiv"> +                Sends the characters contained in message to this device, as if they +                had been typed on the device's keyboard. This is equivalent to calling +                <code><a href="#press">press()</a></code> for each keycode in <code>message</code> +                using the key event type <code><a href="#ACTION_DOWN_AND_UP"></a>DOWN_AND_UP</code>. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#touch">wake</a> +                </span> +                   () +            </nobr> +            <div class="jd-descrdiv"> +                Wakes the screen of this device. +            </div> +        </td> +    </tr> +</table> +<!-- ========= ENUM CONSTANTS DETAIL ======== --> +<h2>Constants</h2> +<A NAME="ACTION_DOWN"></a> +<div class="jd-details api"> +    <h4 class="jd-details-title"> +        <span class="normal"> +            <em>string</em> +        </span> +            DOWN +    </h4> +    <div class="jd-details-descr"> +        <div class="jd-tagdata jd-tagdescr"> +            <p> +                <code><a href="#press">press()</a></code> or +                <code><a href="#press">touch()</a></code> value. +                Specifies that a DOWN event type should be sent to the device, corresponding to +                pressing down on a key or touching the screen. +            </p> +        </div> +    </div> +</div> +<A NAME="ACTION_UP"></A> +<div class="jd-details api"> +    <h4 class="jd-details-title"> +        <span class="normal"> +            <em>string</em> +        </span> +            UP +    </h4> +    <div class="jd-details-descr"> +        <div class="jd-tagdata jd-tagdescr"> +            <p> +                <code><a href="#press">press()</a></code> or +                <code><a href="#press">touch()</a></code> value. +                Specifies that an UP event type should be sent to the device, corresponding to +                releasing a key or lifting up from the screen. +            </p> +        </div> +    </div> +</div> +<A NAME="ACTION_DOWN_AND_UP"></A> + +<div class="jd-details api"> +    <h4 class="jd-details-title"> +        <span class="normal"> +            <em>string</em> +        </span> +            DOWN_AND_UP +    </h4> +    <div class="jd-details-descr"> +        <div class="jd-tagdata jd-tagdescr"> +            <p> +                <code><a href="#press">press()</a></code>, +                <code><a href="#press">touch()</a></code> or +                <code><a href="#type">type()</a></code> value. +                Specifies that a DOWN event type followed by an UP event type should be sent to the +                device, corresponding to typing a key or clicking the screen. +            </p> +        </div> +    </div> +</div> +<!-- ========= METHOD DETAIL ======== --> +<!-- Public methods --> +<h2>Public Methods</h2> +<A NAME="broadcastIntent"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">broadcastIntent</span> +      <span class="normal"> +      ( +            <em>string</em> uri, +            <em>string</em> action, +            <em>string</em> data, +            <em>string</em> mimetype, +            <em>iterable</em> categories +            <em>dictionary</em> extras, +            <em>component</em> component, +            <em>iterable</em> flags) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Broadcasts an Intent to this device, as if the Intent were coming from an +            application. See {@link android.content.Intent Intent} for more information about the +            arguments. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>uri</th> +            <td> +                The URI for the Intent. +                (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}). +            </td> +        </tr> +        <tr> +            <th>action</th> +            <td> +                The action for this Intent +                (see {@link android.content.Intent#setAction(java.lang.String) Intent.setAction()}). +            </td> +        </tr> +        <tr> +            <th>data</th> +            <td> +                The data URI for this Intent +                (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}). +            </td> +        </tr> +        <tr> +            <th>mimetype</th> +            <td> +                The MIME type for the Intent +                (see {@link android.content.Intent#setType(java.lang.String) Intent.setType()}). +            </td> +        </tr> +        <tr> +            <th>categories</th> +            <td> +                An iterable data structure containing strings that define categories for this +                Intent +                (see +                {@link android.content.Intent#addCategory(java.lang.String) Intent.addCategory()}). +            </td> +        </tr> +        <tr> +            <th>extras</th> +            <td> +                A dictionary of extra data for this Intent +                (see {@link android.content.Intent#putExtra(java.lang.String,java.lang.String) +                Intent.putExtra()} +                for an example). +                <p> +                    The key for each dictionary item should be a <em>string</em>. The item's value +                    can be any simple or structured data type. +                </p> +            </td> +        </tr> +        <tr> +            <th>component</th> +            <td> +                The component for this Intent (see {@link android.content.ComponentName}). +                Using this argument will direct the Intent to a specific class within a specific +                Android package. +            </td> +        </tr> +        <tr> +            <th>flags</th> +            <td> +                An iterable data structure containing flags that control how the Intent is handled +                (see {@link android.content.Intent#setFlags(int) Intent.setFlags()}). +            </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="drag"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">drag</span> +      <span class="normal"> +      ( +            <em>tuple</em> start, +            <em>tuple</em> end, +            <em>float</em> duration, +            <em>integer</em> steps) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Simulates a drag gesture (touch, hold, and move) on this device's screen. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>start</th> +          <td> +            The starting point of the drag gesture, in the form of a <em>tuple</em> +            (x,y) where x and y are <em>integers</em>. +          </td> +        </tr> +        <tr> +          <th>end</th> +          <td> +            The end point of the drag gesture, in the form of a <em>tuple</em> (x,y) +            where x and y are <em>integers</em>. +          </td> +        </tr> +        <tr> +            <th>duration</th> +            <td>The duration of the drag gesture in seconds. The default is 1.0 seconds.</td> +        </tr> +        <tr> +            <th>steps</th> +            <td>The number of steps to take when interpolating points. The default is 10.</td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="getProperty"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>object</em> +      </span> +      <span class="sympad">getProperty</span> +      <span class="normal"> +        (<em>string</em> key) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Given the name of a system environment variable, returns its value for this device. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>key</th> +          <td> +            The name of the system environment variable. The available variable names are listed in +            <a href="#table1">Table 1. Property variable names</a> at the end of this topic. +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            The value of the variable. The data format varies according to the variable requested. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="getSystemProperty"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>object</em> +      </span> +      <span class="sympad">getSystemProperty</span> +      <span class="normal"> +      (<em>string</em> key) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Synonym for <code><a href="#getProperty">getProperty()</a></code>. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>key</th> +          <td> +            The name of the system environment variable. The available variable names are listed in +            <a href="#table1">Table 1. Property Variable Names</a>. +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            The value of the variable. The data format varies according to the variable requested. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="installPackage"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">installPackage</span> +      <span class="normal"> +      (<em>string</em> path) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Installs the Android application or test package contained in packageFile +            onto this device. If the application or test package is already installed, it is +            replaced. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>path</th> +          <td> +            The fully-qualified path and filename of the <code>.apk</code> file to install. +          </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="instrument"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>dictionary</em> +      </span> +      <span class="sympad">instrument</span> +      <span class="normal"> +      ( +            <em>string</em> className, +            <em>dictionary</em> args) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Runs the specified component with Android instrumentation, and returns the results +            in a dictionary whose exact format is dictated by the component being run. The +            component must already be present on this device. +        </p> +        <p> +            Use this method to start a test case that uses one of Android's test case classes. +            See <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing +            Fundamentals</a> to learn more about unit testing with the Android testing +            framework. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>className</th> +          <td> +            The name of an Android component that is already installed on this device, in the +            standard form packagename/classname, where packagename is the +            Android package name of a <code>.apk</code> file on this device, and +            classname is the class name of an Android component (Activity, +            ContentProvider, Service, or BroadcastReceiver) in that file. Both +            packagename and classname must be fully qualified. See +            {@link android.content.ComponentName} for more details. +          </td> +        </tr> +        <tr> +          <th>args</th> +          <td> +            A dictionary containing flags and their values. These are passed to the component as it +            is started. If the flag does not take a value, set its dictionary value to an empty +            string. +          </td> +        </tr> +      </table> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +        <ul class="nolist"> +            <li> +                <p> +                    A dictionary containing the component's output. The contents of the dictionary +                    are defined by the component itself. +                </p> +                <p> +                    If you use {@link android.test.InstrumentationTestRunner} as the class name in +                    the componentName argument, then the result dictionary contains +                    the single key "stream". The value of "stream" is a <em>string</em> containing +                    the test output, as if <code>InstrumentationTestRunner</code> was run from the +                    command line. The format of this output is described in +                    <a href="{@docRoot}guide/developing/testing/testing_otheride.html"> +                    Testing in Other IDEs</a>. +                </p> +            </li> +        </ul> +    </div> +    </div> +  </div> +</div> +<A NAME="press"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">press</span> +      <span class="normal"> +      (<em>string</em> name, +      <em>integer</em> type) +      </span> +    </h4> +  <div class="jd-details-descr"> +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Sends the key event specified by <code>type</code> to the key specified by +            <code>keycode</code>. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>name</th> +          <td> +            The name of the keycode to send. See {@link android.view.KeyEvent} for a list of +            keycode names. Use the keycode name, not its integer value. +          </td> +        </tr> +        <tr> +          <th>type</th> +          <td> +            The type of key event to send. The allowed values are <code><a href="#ACTION_DOWN"> +            DOWN</a></code>, <code><a href="#ACTION_UP">UP</a></code>, and +            <code><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></code>. +          </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="reboot"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">reboot</span> +      <span class="normal"> +      (<em>string</em> bootloadType) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +                Reboots this device into the bootloader specified by <code>bootloadType</code>. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>into</th> +          <td> +            The type of bootloader to reboot into. The allowed values are +            "bootloader", "recovery", or "None". +          </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="removePackage"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">removePackage</span> +      <span class="normal"> +      (<em>string</em> package) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Deletes the specified package from this device, including its data and cache. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>package</th> +          <td> +            The Android package name of an <code>.apk</code> file on this device. +          </td> +      </table> +    </div> +  </div> +</div> +<A NAME="shell"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>object</em> +      </span> +      <span class="sympad">shell</span> +      <span class="normal"> +      (<em>string</em> cmd) +      </span> +    </h4> +  <div class="jd-details-descr"> +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Executes an <code>adb</code> shell command and returns the result, if any. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>cmd</th> +          <td> +            The command to execute in the <code>adb</code> shell. The form of these commands is +            described in the topic <a href="{@docRoot}guide/developing/tools/adb.html">Android +            Debug Bridge</a>. +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            The results of the command, if any. The format of the results is determined by the +            command. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="startActivity"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">startActivity</span> +      <span class="normal"> +      ( +            <em>string</em> uri, +            <em>string</em> action, +            <em>string</em> data, +            <em>string</em> mimetype, +            <em>iterable</em> categories +            <em>dictionary</em> extras, +            <em>component</em> component, +            <em>iterable</em> flags) +      </span> +    </h4> +  <div class="jd-details-descr"> +    <div class="jd-tagdata jd-tagdescr"> +        <p> +           Starts an Activity on this device by sending an Intent constructed from the +           supplied arguments. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>uri</th> +          <td> +            The URI for the Intent. +            (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}). +          </td> +        </tr> +        <tr> +            <th>action</th> +            <td> +                The action for the Intent +                (see {@link android.content.Intent#setAction(java.lang.String) Intent.setAction()}). +            </td> +        </tr> +        <tr> +            <th>data</th> +            <td> +                The data URI for the Intent +                (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}). +            </td> +        </tr> +        <tr> +            <th>mimetype</th> +            <td> +                The MIME type for the Intent +                (see {@link android.content.Intent#setType(java.lang.String) Intent.setType()}). +            </td> +        </tr> +        <tr> +            <th>categories</th> +            <td> +                An iterable data structure containing strings that define categories for the +                Intent +                (see +                {@link android.content.Intent#addCategory(java.lang.String) Intent.addCategory()}). +            </td> +        </tr> +        <tr> +            <th>extras</th> +            <td> +                A dictionary of extra data for the Intent +                (see +                {@link android.content.Intent#putExtra(java.lang.String,java.lang.String) +                Intent.putExtra()} +                for an example). +                <p> +                    The key for each dictionary item should be a <em>string</em>. The item's value +                    can be any simple or structured data type. +                </p> +            </td> +        </tr> +        <tr> +            <th>component</th> +            <td> +                The component for the Intent +                (see {@link android.content.ComponentName}). Using this argument will direct the +                Intent to a specific class within a specific Android package. +            </td> +        </tr> +        <tr> +            <th>flags</th> +            <td> +                An iterable data structure containing flags that control how the Intent is handled +                (see {@link android.content.Intent#setFlags(int) Intent.setFlags()}). +            </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="takeSnapshot"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <code> +            <a href="{@docRoot}guide/developing/tools/MonkeyImage.html"> +                MonkeyImage +            </a> +        </code> +      </span> +      <span class="sympad">takeSnapshot</span> +      <span class="normal"> +      () +      </span> +    </h4> +  <div class="jd-details-descr"> +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Captures the entire screen buffer of this device, yielding a +            screen capture of the current display. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            A <a href="{@docRoot}guide/developing/tools/MonkeyImage.html"> +            MonkeyImage</a> object containing the image of the current display. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="touch"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">touch</span> +      <span class="normal"> +      ( +            <em>integer</em> x, +            <em>integer</em> y, +            <em>string</em> type) +      </span> +    </h4> +  <div class="jd-details-descr"> +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Sends a touch event specified by type to the screen location specified +            by x and y. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>x</th> +          <td> +            The horizontal position of the touch in actual device pixels, starting from the left of +            the screen in its current orientation. +          </td> +        </tr> +        <tr> +          <th>y</th> +          <td> +            The vertical position of the touch in actual device pixels, starting from the top of +            the screen in its current orientation. +          </td> +        </tr> +        <tr> +            <th>type</th> +            <td> +                The type of key event to send. The allowed values are <code><a href="#ACTION_DOWN"> +                DOWN</a></code>, <code><a href="#ACTION_UP">UP</a></code>, and +                <code><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></code>. +            </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="type"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">type</span> +      <span class="normal"> +      (<em>string</em> message) +      </span> +    </h4> +  <div class="jd-details-descr"> +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Sends the characters contained in message to this device, as if they +            had been typed on the device's keyboard. This is equivalent to calling +            <code><a href="#press">press()</a></code> for each keycode in <code>message</code> +            using the key event type <code><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></code>. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>message</th> +          <td> +              A string containing the characters to send. +          </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="wake"></A> +<div class="jd-details api"> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">wake</span> +      <span class="normal"> +      () +      </span> +    </h4> +  <div class="jd-details-descr"> +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Wakes the screen of this device. +        </p> +    </div> +  </div> +</div> +<hr></hr> +<h2>Appendix</h2> +    <p class="table-caption" id="table1"> +        <strong>Table 1.</strong>Property variable names used with +        <span class="sympad"><a href="#getProperty">getProperty()</a></span> and +        <span class="sympad"><a href="#getSystemProperty">getSystemProperty()</a></span>. +    </p> +    <table> +        <tr> +            <th> +                Property Group +            </th> +            <th> +                Property +            </th> +            <th> +                Description +            </th> +            <th> +                Notes +            </th> +        </tr> +        <tr> +            <td rowspan="17"><code>build</code></td> +            <td><code>board</code></td> +            <td>Code name for the device's system board</td> +            <td rowspan="17"> +                See {@link android.os.Build} +            </td> +        </tr> +        <tr> +            <td><code>brand</code></td> +            <td>The carrier or provider for which the OS is customized.</td> +        </tr> +            <tr> +            <td><code>device</code></td> +            <td>The device design name.</td> +        </tr> +            <tr> +            <td><code>fingerprint</code></td> +            <td>A unique identifier for the currently-running build.</td> +        </tr> +            <tr> +            <td><code>host</code></td> +            <td></td> +        </tr> +            <tr> +            <td><code>ID</code></td> +            <td>A changelist number or label.</td> +        </tr> +            <tr> +            <td><code>model</code></td> +            <td>The end-user-visible name for the device.</td> +        </tr> +            <tr> +            <td><code>product</code></td> +            <td>The overall product name.</td> +        </tr> +            <tr> +            <td><code>tags</code></td> +            <td>Comma-separated tags that describe the build, such as "unsigned" and "debug".</td> +        </tr> +            <tr> +            <td><code>type</code></td> +            <td>The build type, such as "user" or "eng".</td> +        </tr> +        <tr> +            <td><code>user</code></td> +            <td></td> +        </tr> +        <tr> +            <td><code>CPU_ABI</code></td> +            <td> +                The name of the native code instruction set, in the form CPU type plus +                ABI convention. +            </td> +        </tr> +        <tr> +            <td><code>manufacturer</code></td> +            <td>The product/hardware manufacturer.</td> +        </tr> +        <tr> +            <td><code>version.incremental</code></td> +            <td> +                The internal code used by the source control system to represent this version +                of the software. +            </td> +        </tr> +        <tr> +            <td><code>version.release</code></td> +            <td>The user-visible name of this version of the software.</td> +        </tr> +        <tr> +            <td><code>version.sdk</code></td> +            <td>The user-visible SDK version associated with this version of the OS.</td> +        </tr> +        <tr> +            <td><code>version.codename</code></td> +            <td> +                The current development codename, or "REL" if this version of the software has been +                released. +            </td> +        </tr> +        <tr> +            <td rowspan="3"><code>display</code></td> +            <td><code>width</code></td> +            <td>The device's display width in pixels.</td> +            <td rowspan="3"> +                See +                {@link android.util.DisplayMetrics} for details. +            </td> +        </tr> +        <tr> +            <td><code>height</code></td> +            <td>The device's display height in pixels.</td> +        </tr> +        <tr> +            <td><code>density</code></td> +            <td> +                The logical density of the display. This is a factor that scales +                DIP (Density-Independent Pixel) units to the device's resolution. DIP is adjusted so +                that 1 DIP is equivalent to one pixel on a 160 pixel-per-inch display. For example, +                on a 160-dpi screen, density = 1.0, while on a 120-dpi screen, density = .75. +                <p> +                    The value does not exactly follow the real screen size, but is adjusted to +                    conform to large changes in the display DPI. See +                    {@link android.util.DisplayMetrics#density} for more details. +                </p> +            </td> +        </tr> +        <tr> +            <td rowspan="6"><code>am.current</code></td> +            <td><code>package</code></td> +            <td>The Android package name of the currently running package.</td> +            <td rowspan="6"> +                The <code>am.current</code> keys return information about the currently-running +                Activity. +            </td> +        </tr> +        <tr> +            <td><code>action</code></td> +            <td> +                The current activity's action. This has the same format as the <code>name</code> +                attribute of the <code>action</code> element in a package manifest. +            </td> +        </tr> +        <tr> +            <td><code>comp.class</code></td> +            <td> +                The class name of the component that started the current Activity. See +                <code><a href="#comppackage">comp.package</a></code> for more details.</td> +        </tr> +        <tr> +            <td><a name="comppackage"><code>comp.package</code></a></td> +            <td> +                The package name of the component that started the current Activity. A component +                is specified by a package name and the name of class that the package contains. +            </td> +        </tr> +        <tr> +            <td><code>data</code></td> +            <td>The data (if any) contained in the Intent that started the current Activity.</td> +        </tr> +        <tr> +            <td><code>categories</code></td> +            <td>The categories specified by the Intent that started the current Activity.</td> +        </tr> +        <tr> +            <td rowspan="3"><code>clock</code></td> +            <td><code>realtime</code></td> +            <td> +                The number of milliseconds since the device rebooted, including deep-sleep +                time. +            </td> +            <td rowspan="3"> +                See {@link android.os.SystemClock} for more information. +            </td> +        </tr> +        <tr> +            <td><code>uptime</code></td> +            <td> +                The number of milliseconds since the device rebooted, <em>not</em> including +                deep-sleep time +            </td> +        </tr> +        <tr> +            <td><code>millis</code></td> +            <td>current time since the UNIX epoch, in milliseconds.</td> +        </tr> +    </table> diff --git a/docs/html/guide/developing/tools/MonkeyImage.jd b/docs/html/guide/developing/tools/MonkeyImage.jd new file mode 100644 index 000000000000..ae85cb532feb --- /dev/null +++ b/docs/html/guide/developing/tools/MonkeyImage.jd @@ -0,0 +1,435 @@ +page.title=MonkeyImage +@jd:body +<style> +    h4.jd-details-title {background-color: #DEE8F1;} +</style> + +<p> +    A monkeyrunner class to hold an image of the device or emulator's screen. The image is +    copied from the screen buffer during a screenshot. This object's methods allow you to +    convert the image into various storage formats, write the image to a file, copy parts of +    the image, and compare this object to other <code>MonkeyImage</code> objects. +</p> +<p> +    You do not need to create new instances of <code>MonkeyImage</code>. Instead, use +<code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html#takeSnapshot"> +MonkeyDevice.takeSnapshot()</a></code> to create a new instance from a screenshot. For example, use: +</p> +<pre> +newimage = MonkeyDevice.takeSnapshot() +</pre> +<h2>Summary</h2> +<table id="pubmethods" class="jd-sumtable"> +    <tr> +        <th colspan="12" style="background-color: #E2E2E2">Methods</th> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>string</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#convertToBytes">convertToBytes</a> +                </span> +                (<em>string</em> format) +            </nobr> +            <div class="jd-descrdiv"> +                Converts the current image to a particular format and returns it as a +                <em>string</em> that you can then access as an <em>iterable</em> of binary bytes. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>tuple</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#getRawPixel">getRawPixel</a> +                </span> +                (<em>integer</em> x, +                <em>integer</em> y) +            </nobr> +            <div class="jd-descrdiv"> +                Returns the single pixel at the image location (x,y), as an +                a <em>tuple</em> of <em>integer</em>, in the form (a,r,g,b). +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>integer</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#getRawPixelInt">getRawPixelInt</a> +                </span> +                (<em>integer</em> x, +                 <em>integer</em> y) +            </nobr> +            <div class="jd-descrdiv"> +                Returns the single pixel at the image location (x,y), as +                a 32-bit <em>integer</em>. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <code> +                    <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a> +                </code> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#getSubImage">getSubImage</a> +                </span> +                (<em>tuple</em> rect) +            </nobr> +            <div class="jd-descrdiv"> +                Creates a new <code>MonkeyImage</code> object from a rectangular selection of the +                current image. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>boolean</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#sameAs">sameAs</a> +                </span> +         (<code><a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a></code> +            other, +            <em>float</em> percent) +            </nobr> +            <div class="jd-descrdiv"> +                Compares this <code>MonkeyImage</code> object to another and returns the result of +                the comparison. The <code>percent</code> argument specifies the percentage +                difference that is allowed for the two images to be "equal". +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>void</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#writeToFile">writeToFile</a> +                </span> +                (<em>string</em> path, +                <em>string</em> format) +            </nobr> +            <div class="jd-descrdiv"> +                Writes the current image to the file specified by <code>filename</code>, in the +                format specified by <code>format</code>. +            </div> +        </td> +    </tr> +</table> +<!-- ========= METHOD DETAIL ======== --> +<!-- Public methods --> +<h2>Public Methods</h2> +<A NAME="convertToBytes"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>string</em> +      </span> +      <span class="sympad">convertToBytes</span> +      <span class="normal"> +      ( +            <em>string</em> format) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Converts the current image to a particular format and returns it as a <em>string</em> +            that you can then access as an <em>iterable</em> of binary bytes. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>format</th> +            <td> +                The desired output format. All of the common raster output formats are supported. +                The default value is "png" (Portable Network Graphics). +            </td> +        </tr> +        </table> +    </div> +</div> +</div> +<A NAME="getRawPixel"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>tuple</em> +      </span> +      <span class="sympad">getRawPixel</span> +      <span class="normal"> +        (<em>integer</em> x, +         <em>integer</em> y) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Returns the single pixel at the image location (x,y), as an +            a <em>tuple</em> of <em>integer</em>, in the form (a,r,g,b). +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>x</th> +          <td> +            The horizontal position of the pixel, starting with 0 at the left of the screen in the +            orientation it had when the screenshot was taken. +          </td> +        </tr> +        <tr> +          <th>y</th> +          <td> +            The vertical position of the pixel, starting with 0 at the top of the screen in the +            orientation it had when the screenshot was taken. +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            A tuple of integers representing the pixel, in the form (a,r,g,b) where +            a is the alpha channel value, and r, g, and b are the red, green, and blue values, +            respectively. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="getRawPixelInt"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>tuple</em> +      </span> +      <span class="sympad">getRawPixelInt</span> +      <span class="normal"> +        (<em>integer</em> x, +         <em>integer</em> y) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Returns the single pixel at the image location (x,y), as an +            an <em>integer</em>. Use this method to economize on memory. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>x</th> +          <td> +            The horizontal position of the pixel, starting with 0 at the left of the screen in the +            orientation it had when the screenshot was taken. +          </td> +        </tr> +        <tr> +          <th>y</th> +          <td> +            The vertical position of the pixel, starting with 0 at the top of the screen in the +            orientation it had when the screenshot was taken. +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            The a,r,g, and b values of the pixel as 8-bit values combined into a 32-bit +            integer, with a as the leftmost 8 bits, r the next rightmost, and so forth. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="getSubImage"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +          <code> +              <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a> +          </code> +      </span> +      <span class="sympad">getSubImage</span> +      <span class="normal"> +        (<em>tuple</em> rect) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +           Creates a new <code>MonkeyImage</code> object from a rectangular selection of the +           current image. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>rect</th> +          <td> +            A tuple (x, y, w, h) specifying the selection. x and y specify the 0-based pixel +            position of the upper left-hand corner of the selection. w specifies the width of the +            region, and h specifies its height, both in units of pixels. +            <p> +                The image's orientation is the same as the screen orientation at the time the +                screenshot was made. +            </p> +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            A new <code>MonkeyImage</code> object containing the selection. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="sameAs"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>boolean</em> +      </span> +      <span class="sympad">sameAs</span> +      <span class="normal"> +      ( +       <code> +           <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a> +       </code> otherImage, +       <em>float</em> percent +      ) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +           Compares this <code>MonkeyImage</code> object to another and returns the result of +           the comparison. The <code>percent</code> argument specifies the percentage +           difference that is allowed for the two images to be "equal". +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>other</th> +          <td> +            Another <code>MonkeyImage</code> object to compare to this one. +          </td> +        </tr> +        <tr> +          <th> +            percent +          </th> +          <td> +            A float in the range 0.0 to 1.0, inclusive, indicating +            the percentage of pixels that need to be the same for the method to return +            <code>true</code>. The default is 1.0, indicating that all the pixels +            must match. +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            Boolean <code>true</code> if the images match, or boolean <code>false</code> otherwise. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="writeToFile"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">writeToFile</span> +      <span class="normal"> +      (<em>string</em> filename, +       <em>string</em> format) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +           Writes the current image to the file specified by <code>filename</code>, in the +           format specified by <code>format</code>. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>path</th> +          <td> +            The fully-qualified filename and extension of the output file. +          </td> +        </tr> +        <tr> +            <th> +                format +            </th> +            <td> +                The output format to use for the file. If no format is provided, then the +                method tries to guess the format from the filename's extension. If no +                extension is provided and no format is specified, then the default format of +                "png" (Portable Network Graphics) is used. +            </td> +        </tr> +      </table> +    </div> +  </div> +</div> diff --git a/docs/html/guide/developing/tools/MonkeyRunner.jd b/docs/html/guide/developing/tools/MonkeyRunner.jd new file mode 100644 index 000000000000..871e06d68182 --- /dev/null +++ b/docs/html/guide/developing/tools/MonkeyRunner.jd @@ -0,0 +1,445 @@ +page.title=MonkeyRunner +@jd:body +<style> +    h4.jd-details-title {background-color: #DEE8F1;} +</style> +<p> +    A monkeyrunner class that contains static utility methods. +</p> +<h2>Summary</h2> +<table id="pubmethods" class="jd-sumtable"> +    <tr> +        <th colspan="12" style="background-color: #E2E2E2">Methods</th> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#alert">alert</a> +                </span> +                (<em>string</em> message, +                 <em>string</em> title, +                 <em>string</em> okTitle) +            </nobr> +            <div class="jd-descrdiv"> +                Displays an alert dialog to the process running the current +                program. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>integer</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#choice">choice</a> +                </span> +                (<em>string</em> message, +                 <em>iterable</em> choices, +                 <em>string</em> title) +            </nobr> +            <div class="jd-descrdiv"> +                Displays a dialog with a list of choices to the process running the current program. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#help">help</a> +                </span> +                (<em>string</em> format) +            </nobr> +            <div class="jd-descrdiv"> +                Displays the monkeyrunner API reference in a style similar to that of Python's +                <code>pydoc</code> tool, using the specified format. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <em>string</em> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#input">input</a> +                </span> +                (<em>string</em> message, +                 <em>string</em> initialValue, +                 <em>string</em> title, +                 <em>string</em> okTitle, +                 <em>string</em> cancelTitle) +            </nobr> +            <div class="jd-descrdiv"> +                Displays a dialog that accepts input. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                void +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#sleep">sleep</a> +                </span> +                (<em>float</em> seconds) +            </nobr> +            <div class="jd-descrdiv"> +                Pauses the current program for the specified number of seconds. +            </div> +        </td> +    </tr> +    <tr class="api" > +        <td class="jd-typecol"> +            <nobr> +                <code> +                    <a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a> +                </code> +            </nobr> +        </td> +        <td class="jd-linkcol" width="100%"> +            <nobr> +                <span class="sympad"> +                    <a href="#waitForConnection">waitForConnection</a> +                </span> +                (<em>float</em> timeout, +                <em>string</em> deviceId) +            </nobr> +            <div class="jd-descrdiv"> +                Tries to make a connection between the <code>monkeyrunner</code> backend and the +                specified device or emulator. +            </div> +        </td> +    </tr> +</table> +<!-- ========= METHOD DETAIL ======== --> +<!-- Public methods --> +<h2>Public Methods</h2> +<A NAME="alert"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>string</em> +      </span> +      <span class="sympad">alert</span> +      <span class="normal"> +      ( +            <em>string</em> message, +            <em>string</em> title, +            <em>string</em> okTitle) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Displays an alert dialog to the process running the current +            program. The dialog is modal, so the program pauses until the user clicks the dialog's +            button. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>message</th> +            <td> +                The message to display in the dialog. +            </td> +        </tr> +        <tr> +            <th>title</th> +            <td> +                The dialog's title. The default value is "Alert". +            </td> +        </tr> +        <tr> +            <th>okTitle</th> +            <td> +                The text displayed in the dialog button. The default value is "OK". +            </td> +        </tr> +        </table> +    </div> +</div> +</div> +<A NAME="choice"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>integer</em> +      </span> +      <span class="sympad">choice</span> +      <span class="normal"> +        (<em>string</em> message, +         <em>iterable</em> choices, +         <em>string</em> title) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Displays a dialog with a list of choices to the process running the current program. The +            dialog is modal, so the program pauses until the user clicks one of the dialog's +            buttons. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>message</th> +          <td> +            The prompt message displayed in the dialog. +          </td> +        </tr> +        <tr> +          <th>choices</th> +          <td> +            A Python iterable containing one or more objects that are displayed as strings. The +            recommended form is an array of strings. +          </td> +        </tr> +        <tr> +            <th> +                title +            </th> +            <td> +               The dialog's title. The default is "Input". +            </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            If the user makes a selection and clicks the "OK" button, the method returns +            the 0-based index of the selection within the iterable. +            If the user clicks the "Cancel" button, the method returns -1. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="help"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">help</span> +      <span class="normal"> +        (<em>string</em> format) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Displays the monkeyrunner API reference in a style similar to that of Python's +            <code>pydoc</code> tool, using the specified format. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>format</th> +          <td> +            The markup format to use in the output. The possible values are "text" for plain text +            or "html" for HTML. +          </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="input"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        <em>string</em> +      </span> +      <span class="sympad">input</span> +      <span class="normal"> +        (<em>string</em> message +         <em>string</em> initialValue, +         <em>string</em> title, +         <em>string</em> okTitle, +         <em>string</em> cancelTitle) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Displays a dialog that accepts input and returns it to the program. The dialog is +            modal, so the program pauses until the user clicks one of the dialog's buttons. +        </p> +        <p> +            The dialog contains two buttons, one of which displays the okTitle value +            and the other the cancelTitle value. If the user clicks the okTitle button, +            the current value of the input box is returned. If the user clicks the cancelTitle +            button, an empty string is returned. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>message</th> +          <td> +            The prompt message displayed in the dialog. +          </td> +        </tr> +        <tr> +          <th>initialValue</th> +          <td> +            The initial value to display in the dialog. The default is an empty string. +          </td> +        </tr> +        <tr> +          <th>title</th> +          <td> +            The dialog's title. The default is "Input". +          </td> +        </tr> +        <tr> +          <th>okTitle</th> +          <td> +            The text displayed in the okTitle button. The default is "OK". +          </td> +        </tr> +        <tr> +          <th>cancelTitle</th> +          <td> +            The text displayed in the cancelTitle button. The default is "Cancel". +          </td> +        </tr> +      </table> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +            If the user clicks the okTitle button, then the method returns the current value of +            the dialog's input box. If the user clicks the cancelTitle button, the method returns +            an empty string. +        </li> +      </ul> +    </div> +  </div> +</div> +<A NAME="sleep"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +        void +      </span> +      <span class="sympad">sleep</span> +      <span class="normal"> +      ( +       <em>float</em> seconds +      ) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Pauses the current program for the specified number of seconds. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>seconds</th> +          <td> +            The number of seconds to pause. +          </td> +        </tr> +      </table> +    </div> +  </div> +</div> +<A NAME="waitForConnection"></A> +<div class="jd-details api "> +    <h4 class="jd-details-title"> +      <span class="normal"> +          <code> +              <a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a> +          </code> +      </span> +      <span class="sympad">waitForConnection</span> +      <span class="normal"> +      (<em>float</em> timeout, +       <em>string</em> deviceId) +      </span> +    </h4> +  <div class="jd-details-descr"> + +    <div class="jd-tagdata jd-tagdescr"> +        <p> +            Tries to make a connection between the <code>monkeyrunner</code> backend and the +            specified device or emulator. +        </p> +    </div> +    <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Arguments</h5> +      <table class="jd-tagtable"> +        <tr> +          <th>timeout</th> +          <td> +            The number of seconds to wait for a connection. The default is to wait forever. +          </td> +        </tr> +        <tr> +            <th> +                deviceId +            </th> +            <td> +                A regular expression that specifies the serial number of the device or emulator. See +                the topic +                <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> +                for a description of device and emulator serial numbers. +            </td> +        </tr> +      </table> +    </div> +        <div class="jd-tagdata"> +      <h5 class="jd-tagtitle">Returns</h5> +      <ul class="nolist"> +        <li> +          A <code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a></code> +          instance for the device or emulator. Use this object to control and communicate with the +          device or emulator. +        </li> +      </ul> +    </div> +  </div> +</div> diff --git a/docs/html/guide/developing/tools/index.jd b/docs/html/guide/developing/tools/index.jd index 6e9fde1fb0f4..0e10377b19c5 100644 --- a/docs/html/guide/developing/tools/index.jd +++ b/docs/html/guide/developing/tools/index.jd @@ -3,27 +3,27 @@ page.title=Tools Overview  <img src="{@docRoot}assets/images/android_wrench.png" alt="" align="right"> -<p>The Android SDK includes a variety of custom tools that help you develop mobile  -applications on the Android platform. The most important of these are the Android  -Emulator and the Android Development Tools plugin for Eclipse, but the SDK also  -includes a variety of other tools for debugging, packaging, and installing your  +<p>The Android SDK includes a variety of custom tools that help you develop mobile +applications on the Android platform. The most important of these are the Android +Emulator and the Android Development Tools plugin for Eclipse, but the SDK also +includes a variety of other tools for debugging, packaging, and installing your  applications on the emulator. </p> -     +   <dl>    <dt><a href="adt.html">Android Development Tools Plugin</a> (for the Eclipse IDE)</dt> -          <dd>The ADT plugin adds powerful extensions to the Eclipse integrated environment,  -          making creating and debugging your Android applications easier and faster. If you  -          use Eclipse, the ADT plugin gives you an incredible boost in developing Android  +          <dd>The ADT plugin adds powerful extensions to the Eclipse integrated environment, +          making creating and debugging your Android applications easier and faster. If you +          use Eclipse, the ADT plugin gives you an incredible boost in developing Android            applications.</dd>    <dt><a href="emulator.html">Android Emulator</a></dt> -    <dd>A QEMU-based device-emulation tool that you can use to design,  +    <dd>A QEMU-based device-emulation tool that you can use to design,      debug, and test your applications in an actual Android run-time environment. </dd>    <dt><a href="avd.html">Android Virtual Devices (AVDs)</a></dt>      <dd>Virtual device configurations that you create, to model device          characteristics in the Android Emulator. In each configuration, you can          specify the Android platform to run, the hardware options, and the -        emulator skin to use. Each AVD functions as an independent device with  +        emulator skin to use. Each AVD functions as an independent device with          it's own storage for user data, SD card, and so on. </dd>   <dt><a href="hierarchy-viewer.html">Hierarchy Viewer</a></dt> @@ -37,53 +37,53 @@ applications on the emulator. </p>  efficiency.      </dd> -	  <dt><a href="draw9patch.html">Draw 9-patch</a></dt> -	    <dd>The Draw 9-patch tool allows you to easily create a  -	    {@link android.graphics.NinePatch} graphic using a WYSIWYG editor. It also previews stretched  -	     versions of the image, and highlights the area in which content is allowed. -	    </dd> +      <dt><a href="draw9patch.html">Draw 9-patch</a></dt> +        <dd>The Draw 9-patch tool allows you to easily create a +        {@link android.graphics.NinePatch} graphic using a WYSIWYG editor. It also previews stretched +         versions of the image, and highlights the area in which content is allowed. +        </dd> -  <dt><a href="ddms.html" >Dalvik Debug Monitor  +  <dt><a href="ddms.html" >Dalvik Debug Monitor        Service</a> (ddms)</dt> -	    <dd>Integrated with Dalvik, the Android platform's custom VM, this tool  -	    lets you manage processes on an emulator or device and assists in debugging.  -	    You can use it to kill processes, select a specific process to debug,  -	    generate trace data, view heap and thread information, take screenshots  -	    of the emulator or device, and more. </dd> -			 +        <dd>Integrated with Dalvik, the Android platform's custom VM, this tool +        lets you manage processes on an emulator or device and assists in debugging. +        You can use it to kill processes, select a specific process to debug, +        generate trace data, view heap and thread information, take screenshots +        of the emulator or device, and more. </dd> +    <dt><a href="adb.html" >Android Debug Bridge</a> (adb)</dt> -                  <dd>The adb tool lets you install your application's .apk files on an  -                  emulator or device and access the emulator or device from a command line.  -                  You can also use it to link a standard debugger to application code running  +                  <dd>The adb tool lets you install your application's .apk files on an +                  emulator or device and access the emulator or device from a command line. +                  You can also use it to link a standard debugger to application code running                    on an Android emulator or device.</dd> -  <dt><a href="aapt.html">Android Asset  +  <dt><a href="aapt.html">Android Asset            Packaging Tool</a> (aapt)</dt> -                  <dd>The aapt tool lets you create .apk files containing the binaries and  +                  <dd>The aapt tool lets you create .apk files containing the binaries and                    resources of Android applications.</dd> -  <dt><a href="aidl.html" >Android Interface  +  <dt><a href="aidl.html" >Android Interface    Description Language</a> (aidl)</dt>              <dd>Lets you generate code for an interprocess interface, such as what              a service might use.</dd>    <dt><a href="adb.html#sqlite">sqlite3</a></dt> -      <dd>Included as a convenience, this tool lets you access the SQLite data  +      <dd>Included as a convenience, this tool lets you access the SQLite data        files created and used by Android applications.</dd>    <dt><a href="traceview.html" >Traceview</a></dt> -            <dd> This tool produces graphical analysis views of trace log data that you  +            <dd> This tool produces graphical analysis views of trace log data that you              can generate from your Android application. </dd>    <dt><a href="othertools.html#mksdcard">mksdcard</a></dt> -            <dd>Helps you create a disk image that you can use with the emulator,  +            <dd>Helps you create a disk image that you can use with the emulator,                        to simulate the presence of an external storage card (such as an SD card).</dd>    <dt><a href="othertools.html#dx">dx</a></dt> -                  <dd>The dx tool rewrites .class bytecode into Android bytecode  +                  <dd>The dx tool rewrites .class bytecode into Android bytecode                                            (stored in .dex files.)</dd> -  <dt><a href="monkey.html">UI/Application  +  <dt><a href="monkey.html">UI/Application    Exerciser Monkey</a></dt>        <dd>The Monkey is a program that runs on your emulator or device and generates pseudo-random        streams of user events such as clicks, touches, or gestures, as well as a number of system- @@ -92,9 +92,9 @@ efficiency.    <dt><a  href="othertools.html#android">android</a></dt>              <dd>A script that lets you manage AVDs and generate <a -                        href="http://ant.apache.org/" title="Ant">Ant</a> build files that  +                        href="http://ant.apache.org/" title="Ant">Ant</a> build files that                          you can use to compile your Android applications. </dd> -                         +    <dt><a  href="zipalign.html">zipalign</a></dt>              <dd>An important .apk optimization tool. This tool ensures that all uncompressed data starts              with a particular alignment relative to the start of the file. This should always be used diff --git a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd new file mode 100644 index 000000000000..18389050ee85 --- /dev/null +++ b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd @@ -0,0 +1,308 @@ +page.title=monkeyrunner +@jd:body + +<div id="qv-wrapper"> +  <div id="qv"> +  <h2>In this document</h2> +  <ol> +    <li> +        <a href="#SampleProgram">A Simple monkeyrunner Program</a> +    </li> +    <li> +        <a href="#APIClasses">The monkeyrunner API</a> +    </li> +    <li> +        <a href="#RunningMonkeyRunner">Running monkeyrunner</a> +    </li> +    <li> +        <a href="#Help">monkeyrunner Built-in Help</a> +    </li> +    <li> +        <a href="#Plugins">Extending monkeyrunner with Plugins</a> +    </li> +  </ol> +  <h2>See Also</h2> +      <ol> +        <li> +            <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a> +        </li> +      </ol> +  </div> +</div> +<p> +    The monkeyrunner tool provides an API for writing programs that control an Android device +    or emulator from outside of Android code. With monkeyrunner, you can write a Python program +    that installs an Android application or test package, runs it, sends keystrokes to it, +    takes screenshots of its user interface, and stores screenshots on the workstation. The +    monkeyrunner tool is primarily designed to test applications and devices at the +    functional/framework level and for running unit test suites, but you are free to use it for +    other purposes. +</p> +<p> +    The monkeyrunner tool is not related to the +    <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>, +    also known as the <code>monkey</code> tool. The <code>monkey</code> tool runs in an +    <code><a href="{@docRoot}guide/developing/tools/adb.html">adb</a></code> shell directly on the +    device or emulator and generates pseudo-random streams of user and system events. In comparison, +    the monkeyrunner tool controls devices and emulators from a workstation by sending specific +    commands and events from an API. +</p> +<p> +    The monkeyrunner tool provides these unique features for Android testing: +</p> +<ul> +    <li> +        Multiple device control: The monkeyrunner API can apply one or more +        test suites across multiple devices or emulators. You can physically attach all the devices +        or start up all the emulators (or both) at once, connect to each one in turn +        programmatically, and then run one or more tests. You can also start up an emulator +        configuration programmatically, run one or more tests, and then shut down the emulator. +    </li> +    <li> +        Functional testing: monkeyrunner can run an automated start-to-finish test of an Android +        application. You provide input values with keystrokes or touch events, and view the results +        as screenshots. +    </li> +    <li> +        Regression testing - monkeyrunner can test application stability by running an application +        and comparing its output screenshots to a set of screenshots that are known to be correct. +    </li> +    <li> +        Extensible automation - Since monkeyrunner is an API toolkit, you can develop an entire +        system of Python-based modules and programs for controlling Android devices. Besides using +        the monkeyrunner API itself, you can use the standard Python +        <code><a href="http://docs.python.org/library/os.html">os</a></code> and +        <code><a href="http://docs.python.org/library/subprocess.html">subprocess</a></code> +        modules to call Android tools such as +        <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>. +        <p> +            You can also add your own classes to the monkeyrunner API. This is described +            in more detail in the section +            <a href="#Plugins">Extending monkeyrunner with plugins</a>. +        </p> +    </li> +</ul> +<p> +    The monkeyrunner tool uses <a href="http://www.jython.org/">Jython</a>, a +    implementation of Python that uses the Java programming language. Jython allows the +    monkeyrunner API to interact easily with the Android framework. With Jython you can +    use Python syntax to access the constants, classes, and methods of the API. +</p> + +<h2 id="SampleProgram">A Simple monkeyrunner Program</h2> +<p> +    Here is a simple monkeyrunner program that connects to a device, creating a +    <code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a></code> +    object. Using the <code>MonkeyDevice</code> object, the program installs an Android application +    package, runs one of its activities, and sends key events to the activity. +    The program then takes a screenshot of the result, creating a +    <code><a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a></code> object. +    From this object, the program writes out a <code>.png</code> file containing the screenshot. +</p> +<pre> +# Imports the monkeyrunner modules used by this program +from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice + +# Connects to the current device, returning a MonkeyDevice object +device = MonkeyRunner.waitForConnection() + +# Installs the Android package. Notice that this method returns a boolean, so you can test +# to see if the installation worked. +device.installPackage('myproject/bin/MyApplication.apk') + +# Runs an activity in the application +device.startActivity(component='com.example.android.myapplication.MainActivity') + +# Presses the Menu button +device.press('KEYCODE_MENU','DOWN_AND_UP') + +# Takes a screenshot +result = device.takeSnapShot + +# Writes the screenshot to a file +result.writeToFile('myproject/shot1.png','png') +</pre> + +<h2 id="APIClasses">The monkeyrunner API</h2> +<p> +    The monkeyrunner API is contained in three modules in the package +    <code>com.android.monkeyrunner</code>: +</p> +<ul> +    <li> +        <code><a href="{@docRoot}guide/developing/tools/MonkeyRunner.html">MonkeyRunner</a></code>: +        A class of utility methods for monkeyrunner programs. This class provides a method for +        connecting monkeyrunner to a device or emulator. It also provides methods for +        creating UIs for a monkeyrunner program and for displaying the built-in help. +    </li> +    <li> +        <code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a></code>: +        Represents a device or emulator. This class provides methods for installing and +        uninstalling packages, starting an Activity, and sending keyboard or touch events to an +        application. You also use this class to run test packages. +    </li> +    <li> +        <code><a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a></code>: +        Represents a screen capture image. This class provides methods for capturing screens, +        converting bitmap images to various formats, comparing two MonkeyImage objects, and +        writing an image to a file. +    </li> +</ul> +<p> +    In a Python program, you access each class as a Python module. The monkeyrunner tool +    does not import these modules automatically. To import a module, use the +    Python <code>from</code> statement: +</p> +<pre> +from com.android.monkeyrunner import <module> +</pre> +<p> +    where <code><module></code> is the class name you want to import. You can import more +    than one module in the same <code>from</code> statement by separating the module names with +    commas. +</p> +<h2 id="RunningMonkeyRunner">Running monkeyrunner</h2> +<p> +    You can either run monkeyrunner programs from a file, or enter monkeyrunner statements in +    an interactive session. You do both by invoking the <code>monkeyrunner</code> command +    which is found in the <code>tools/</code> subdirectory of your SDK directory. +    If you provide a filename as an argument, the <code>monkeyrunner</code> command +    runs the file's contents as a Python program; otherwise, it starts an interactive session. +</p> +<p> +    The syntax of the <code>monkeyrunner</code> command is +</p> +<pre> +monkeyrunner -plugin <plugin_jar> <program_filename> <program_options> +</pre> +<p> +Table 1 explains the flags and arguments. +</p> +<p class="table-caption" id="table1"> +  <strong>Table 1.</strong> <code>monkeyrunner</code> flags and arguments.</p> + +<table> +    <tr> +        <th>Argument</th> +        <th>Description</th> +    </tr> +    <tr> +        <td> +            <nobr> +                <code>-plugin <plugin_jar></code> +            </nobr> +        </td> +        <td> +            (Optional) Specifies a <code>.jar</code> file containing a plugin for monkeyrunner. +            To learn more about monkeyrunner plugins, see +            <a href="#Plugins">Extending monkeyrunner with plugins</a>. To specify more than one +            file, include the argument multiple times. +        </td> +    </tr> +    <tr> +        <td> +            <nobr> +                <code><program_filename></code> +            </nobr> +        </td> +        <td> +            If you provide this argument, the <code>monkeyrunner</code> command runs the contents +            of the file as a Python program. If the argument is not provided, the command starts an +            interactive session. +        </td> +    </tr> +    <tr> +        <td> +            <code><program_options></code> +        </td> +        <td> +            (Optional) Flags and arguments for the program in <program_file>. +        </td> +    </tr> +</table> +<h2 id="Help">monkeyrunner Built-in Help</h2> +<p> +    You can generate an API reference for monkeyrunner by running: +</p> +<pre> +monkeyrunner <format> help.py <outfile> +</pre> +<p> +The arguments are: +</p> +    <ul> +        <li> +            <code><format></code> is either <code>text</code> for plain text output +            or <code>html</code> for HTML output. +        </li> +        <li> +            <code><outfile></code> is a path-qualified name for the output file. +        </li> +    </ul> +<h2 id="Plugins">Extending monkeyrunner with Plugins</h2> +<p> +    You can extend the monkeyrunner API with classes you write in the Java programming language +    and build into one or more <code>.jar</code> files. You can use this feature to extend the +    monkeyrunner API with your own classes or to extend the existing classes. You can also use this +    feature to initialize the monkeyrunner environment. +</p> +<p> +    To provide a plugin to monkeyrunner, invoke the <code>monkeyrunner</code> command with the +    <code>-plugin <plugin_jar></code> argument described in +    <a href="#table1">table 1</a>. +</p> +<p> +    In your plugin code, you can import and extend the the main monkeyrunner classes +    <code>MonkeyDevice</code>, <code>MonkeyImage</code>, and <code>MonkeyRunner</code> in +    <code>com.android.monkeyrunner</code> (see <a href="#APIClasses">The monkeyrunner API</a>). +</p> +<p> +    Note that plugins do not give you access to the Android SDK. You can't import packages +    such as <code>com.android.app</code>. This is because monkeyrunner interacts with the +    device or emulator below the level of the framework APIs. +</p> +<h3>The plugin startup class</h3> +<p> +    The <code>.jar</code> file for a plugin can specify a class that is instantiated before +    script processing starts. To specify this class, add the key +    <code>MonkeyRunnerStartupRunner</code> to the <code>.jar</code> file's +    manifest. The value should be the name of the class to run at startup. The following +    snippet shows how you would do this within an <code>ant</code> build script: +</p> +<pre> +<jar jarfile="myplugin" basedir="${build.dir}"> +<manifest> +<attribute name="MonkeyRunnerStartupRunner" value="com.myapp.myplugin"/> +</manifest> +</jar> + + +</pre> +<p> +    To get access to monkeyrunner's runtime environment, the startup class can implement +    <code>com.google.common.base.Predicate<PythonInterpreter></code>. For example, this +    class sets up some variables in the default namespace: +</p> +<pre> +package com.android.example; + +import com.google.common.base.Predicate; +import org.python.util.PythonInterpreter; + +public class Main implements Predicate<PythonInterpreter> { +    @Override +    public boolean apply(PythonInterpreter anInterpreter) { + +        /* +        * Examples of creating and initializing variables in the monkeyrunner environment's +        * namespace. During execution, the monkeyrunner program can refer to the variables "newtest" +        * and "use_emulator" +        * +        */ +        anInterpreter.set("newtest", "enabled"); +        anInterpreter.set("use_emulator", 1); + +        return true; +    } +} +</pre> diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 2b803424c264..a43e33474087 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -254,34 +254,45 @@              <li><a href="<?cs var:toroot?>guide/topics/search/searchable-config.html">Searchable Configuration</a></li>            </ul>        </li> +      <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html"> +            <span class="en">Device Administration</span> +         </a> <span class="new">new!</span> +      </li>        <li class="toggle-list">             <div> -                <a href="<?cs var:toroot ?>guide/topics/testing/index.html"> +                <a href="<?cs var:toroot?>guide/topics/testing/index.html">                     <span class="en">Testing</span> -               </a> <span class="new">new!</span> +               </a>             </div>             <ul> -              <li><a href="<?cs var:toroot?>guide/topics/testing/testing_android.html"> +              <li> +                <a href="<?cs var:toroot?>guide/topics/testing/testing_android.html">                  <span class="en">Testing Fundamentals</span></a> +                <span class="new">new!</span>                </li> -              <li><a href="<?cs var:toroot?>guide/topics/testing/activity_testing.html"> +              <li> +                <a href="<?cs var:toroot?>guide/topics/testing/activity_testing.html">                  <span class="en">Activity Testing</span></a> +                <span class="new">new!</span>                </li> -              <li><a href="<?cs var:toroot ?>guide/topics/testing/contentprovider_testing.html"> +              <li> +                <a href="<?cs var:toroot?>guide/topics/testing/contentprovider_testing.html">                  <span class="en">Content Provider Testing</span></a> +                <span class="new">new!</span>                </li> -              <li><a href="<?cs var:toroot ?>guide/topics/testing/service_testing.html"> +              <li> +                <a href="<?cs var:toroot?>guide/topics/testing/service_testing.html">                  <span class="en">Service Testing</span></a> +                <span class="new">new!</span>                </li> -              <li><a href="<?cs var:toroot ?>guide/topics/testing/what_to_test.html"> +              <li> +                <a href="<?cs var:toroot ?>guide/topics/testing/what_to_test.html">                  <span class="en">What To Test</span></a> +                <span class="new">new!</span>                </li> +             </ul>        </li> -     <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html"> -            <span class="en">Device Administration</span> -         </a> <span class="new">new!</span> -    </li>      </ul>    </li> @@ -336,6 +347,7 @@                    <span class="en">Testing in Eclipse, with ADT</span>                  </a>                </li> +                <li>                  <a href="<?cs var:toroot ?>guide/developing/testing/testing_otheride.html">                    <span class="en">Testing in Other IDEs</span> @@ -363,6 +375,34 @@                <li><a href="<?cs var:toroot ?>guide/developing/tools/layoutopt.html">layoutopt</a></li>                <li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#mksdcard">mksdcard</a></li>                <li><a href="<?cs var:toroot ?>guide/developing/tools/monkey.html">Monkey</a></li> +                            <li class="toggle-list"> +                 <div> +                     <a href="<?cs var:toroot?>guide/developing/tools/monkeyrunner_concepts.html"> +                     <span class="en">monkeyrunner</span> +                  </a> +                      <span class="new">new!</span> +                  </div> +                  <ul> +                      <li> +                          <a href="<?cs var:toroot?>guide/developing/tools/MonkeyDevice.html"> +                                <span class="en">MonkeyDevice</span> +                        </a> +                        <span class="new">new!</span> +                    </li> +                    <li> +                        <a href="<?cs var:toroot?>guide/developing/tools/MonkeyImage.html"> +                            <span class="en">MonkeyImage</span> +                        </a> +                        <span class="new">new!</span> +                    </li> +                    <li> +                        <a href="<?cs var:toroot?>guide/developing/tools/MonkeyRunner.html"> +                            <span class="en">MonkeyRunner</span> +                        </a> +                        <span class="new">new!</span> +                    </li> +                  </ul> +              </li>                <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html#sqlite">sqlite3</a></li>                <li><a href="<?cs var:toroot ?>guide/developing/tools/traceview.html" >Traceview</a></li>                <li><a href="<?cs var:toroot ?>guide/developing/tools/zipalign.html" >zipalign</a></li> diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd index 1d6ab259c355..d86859905e86 100644 --- a/docs/html/guide/topics/resources/providing-resources.jd +++ b/docs/html/guide/topics/resources/providing-resources.jd @@ -129,9 +129,8 @@ Menu. See <a href="menu-resource.html">Menu Resource</a>.</td>    <tr>      <td><code>raw/</code></td> -    <td><p>Arbitrary files to save in their raw form. Files in here are not compressed by the -system. To open these resources with a raw {@link java.io.InputStream}, call {@link -android.content.res.Resources#openRawResource(int) +    <td><p>Arbitrary files to save in their raw form. To open these resources with a raw +{@link java.io.InputStream}, call {@link android.content.res.Resources#openRawResource(int)  Resources.openRawResource()} with the resource ID, which is {@code R.raw.<em>filename</em>}.</p>        <p>However, if you need access to original file names and file hierarchy, you might consider  saving some resources in the {@code diff --git a/docs/html/guide/topics/testing/index.jd b/docs/html/guide/topics/testing/index.jd index b75656f14392..762a8975d970 100644 --- a/docs/html/guide/topics/testing/index.jd +++ b/docs/html/guide/topics/testing/index.jd @@ -59,6 +59,20 @@ page.title=Testing          which guides you through a more complex testing scenario.      </li>  </ul> +<h4>Tools</h4> +<ul> +    <li> +        The +        <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>, +        usually called Monkey, is a command-line tool that sends pseudo-random +        streams of keystrokes, touches, and gestures to a device. +    </li> +    <li> +     The <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a> tool +        is an API and execution environment. You use monkeyrunner with Python programs +        to test applications and devices. +    </li> +</ul>  <h4>Samples</h4>  <ul>      <li> diff --git a/docs/html/guide/topics/testing/testing_android.jd b/docs/html/guide/topics/testing/testing_android.jd index 2a4c9492685a..d4b0dcc24f1f 100755 --- a/docs/html/guide/topics/testing/testing_android.jd +++ b/docs/html/guide/topics/testing/testing_android.jd @@ -38,7 +38,7 @@ page.title=Testing Fundamentals          <a href="#TestResults">Seeing Test Results</a>      </li>      <li> -        <a href="#Monkeys">Monkey and MonkeyRunner</a> +        <a href="#Monkeys">monkey and monkeyrunner</a>      </li>      <li>         <a href="#PackageNames">Working With Package Names</a> @@ -77,6 +77,13 @@ page.title=Testing Fundamentals            <a href="{@docRoot}guide/developing/testing/testing_otheride.html">            Testing in Other IDEs</a>          </li> +        <li> +          <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html"> +          monkeyrunner</a> +        </li> +        <li> +     <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a> +        </li>        </ol>    </div>  </div> @@ -112,10 +119,10 @@ page.title=Testing Fundamentals      </li>      <li>          The SDK also provides -        <a href="{@docRoot}guide/topics/testing/monkeyrunner.html">MonkeyRunner</a>, an API for -        testing devices with Jython scripts, and <a -        href="{@docRoot}guide/developing/tools/monkey.html">Monkey</a>, a command-line tool for -        stress-testing UIs by sending pseudo-random events to a device. +  <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a>, an API +        testing devices with Python programs, and <a +        href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>, +        a command-line tool for stress-testing UIs by sending pseudo-random events to a device.      </li>  </ul>  <p> @@ -540,25 +547,28 @@ page.title=Testing Fundamentals      <a href="{@docRoot}guide/developing/testing/testing_otheride.html#RunTestsCommand">      Testing in Other IDEs</a>.  </p> -<h2 id="Monkeys">Monkey and MonkeyRunner</h2> +<h2 id="Monkeys">monkey and monkeyrunner</h2>  <p>      The SDK provides two tools for functional-level application testing:  </p>      <ul>          <li> -            <a href="{@docRoot}guide/developing/tools/monkey.html">Monkey</a> is a command-line -            tool that sends pseudo-random streams of keystrokes, touches, and gestures to a -            device. You run it with the <a href="{@docRoot}guide/developing/tools/adb.html"> -            Android Debug Bridge</a> (adb) tool. You use it to stress-test your application and -            report back errors that are encountered. You can repeat a stream of events by -            running the tool each time with the same random number seed. +The <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>, +            usually called "monkey", is a command-line tool that sends pseudo-random streams of +            keystrokes, touches, and gestures to a device. You run it with the +            <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (adb) tool. +            You use it to stress-test your application and report back errors that are encountered. +            You can repeat a stream of events by running the tool each time with the same random +            number seed.          </li>          <li> -            <a href="{@docRoot}guide/topics/testing/monkeyrunner.html">MonkeyRunner</a> is a -            Jython API that you use in test programs written in Python. The API includes functions -            for connecting to a device, installing and uninstalling packages, taking screenshots, -            comparing two images, and running a test package against an application. Using the API -            with Python, you can write a wide range of large, powerful, and complex tests. +    The <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a> tool +            is an API and execution environment for test programs written in Python. The API +            includes functions for connecting to a device, installing and uninstalling packages, +            taking screenshots, comparing two images, and running a test package against an +            application. Using the API, you can write a wide range of large, powerful, and complex +            tests. You run programs that use the API with the <code>monkeyrunner</code> command-line +            tool.          </li>      </ul>  <h2 id="PackageNames">Working With Package names</h2> diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd index 3b4ccb0e0b24..cef057e30f7d 100644 --- a/docs/html/resources/dashboard/platform-versions.jd +++ b/docs/html/resources/dashboard/platform-versions.jd @@ -52,7 +52,7 @@ Android Market within a 14-day period ending on the data collection date noted b  <div class="dashboard-panel">  <img alt="" height="250" width="460" -src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:9.7,16.4,0.1,40.4,33.4&chl= +src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:7.9,15.0,0.1,40.8,36.2&chl=  Android%201.5|Android%201.6|Other*|Android%202.1|Android%202.2&chco=c4df9b,  6fad0c" /> @@ -62,13 +62,13 @@ Android%201.5|Android%201.6|Other*|Android%202.1|Android%202.2&chco=c4df9b,    <th>API Level</th>    <th>Distribution</th>  </tr> -<tr><td>Android 1.5</td><td>3</td><td>9.7%</td></tr> -<tr><td>Android 1.6</td><td>4</td><td>16.4%</td></tr> -<tr><td>Android 2.1</td><td>7</td><td>40.4%</td></tr> -<tr><td>Android 2.2</td><td>8</td><td>33.4%</td></tr> +<tr><td>Android 1.5</td><td>3</td><td>7.9%</td></tr> +<tr><td>Android 1.6</td><td>4</td><td>15.0%</td></tr> +<tr><td>Android 2.1</td><td>7</td><td>40.8%</td></tr> +<tr><td>Android 2.2</td><td>8</td><td>36.2%</td></tr>  </table> -<p><em>Data collected during two weeks ending on October 1, 2010</em></p> +<p><em>Data collected during two weeks ending on November 1, 2010</em></p>  <p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>  </div><!-- end dashboard-panel --> @@ -96,19 +96,18 @@ Android Market within a 14-day period ending on the date indicated on the x-axis  <div class="dashboard-panel">  <img alt="" height="250" width="660" style="padding:5px;background:#fff" -src="http://chart.apis.google.com/chart?cht=lc&chs=660x250&chxt=x,y,r&chxr=0,0,12|1,0,100|2,0,100& -chxl=0:|2010/04/01|04/15|05/01|05/15|06/01|06/15|07/01|07/15|08/01|08/15|09/01|09/15|2010/10/01|1:|0 -%25|25%25|50%25|75%25|100%25|2:|0%25|25%25|50%25|75%25|100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12& -chxtc=0,5&chd=t:99.6,99.6,99.6,99.7,100.6,101.1,99.9,100.0,100.0,99.8,99.9,100.0,100.0|61.5,61.7,62. -3,63.5,73.0,76.4,78.6,81.1,84.5,86.6,88.0,89.3,90.3|29.4,30.2,32.7,35.3,46.2,51.3,55.1,59.0,64.1,68. -2,70.4,72.2,73.9|4.0,28.3,32.0,34.9,45.9,51.0,54.9,58.8,64.0,68.1,70.3,72.1,73.8|0.0,0.0,0.0,0.0,0.8 -,1.2,1.8,3.3,4.3,11.3,27.8,32.1,33.4&chm=tAndroid+1.5,7caa36,0,0,15,,t::-5|b,c3df9b,0,1,0|tAndroid+1 -.6,638d23,1,0,15,,t::-5|b,b0db6e,1,2,0|tAndroid+2.0.1,496c13,2,0,15,,t::-5|b,9ddb3d,2,3,0|tAndroid+2 -.1,2f4708,3,1,15,,t:-30:-40|b,89cf19,3,4,0|tAndroid+2.2,131d02,4,9,15,,t::-5|B,6fad0c,4,5,0&chg=7,25 -&chdl=Android+1.5|Android+1.6|Android+2.0.1|Android+2.1|Android+2.2&chco=add274,9ad145,84c323,6ba213 -,507d08" /> - -<p><em>Last historical dataset collected during two weeks ending on October 1, 2010</em></p> +src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,y,r&chxr=0,0,12|1,0,100|2,0,100& +chxl=0%3A%7C2010/05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C09/15%7C10/ +01%7C10/15%7C2010/11/01%7C1%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C2%3A%7C0%25%7C25%25%7C50%25 +%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:98.9,99.3,100.3,100.8,99.7,99. +8,99.8,99.7,99.8,99.9,99.9,99.9,99.9|61.6,63.1,72.7,76.1,78.4,80.9,84.3,86.5,87.9,89.2,90.2,91.1,92. +0|32.0,34.9,45.9,51.0,54.9,58.8,64.0,68.1,70.3,72.1,73.8,75.3,77.0|0.0,0.0,0.8,1.2,1.8,3.3,4.3,11.3, +27.8,32.1,33.4,34.5,36.2&chm=tAndroid%201.5,7caa36,0,0,15,,t::-5|b,c3df9b,0,1,0|tAndroid%201.6, +5b831d,1,0,15,,t::-5|b,aadb5e,1,2,0|tAndroid%202.1,38540b,2,0,15,,t::-5|b,91da1e,2,3,0|tAndroid%202. +2,131d02,3,7,15,,t::-5|B,6fad0c,3,4,0&chg=7,25&chdl=Android%201.5|Android%201.6|Android%202.1| +Android%202.2&chco=add274,94d134,73ad18,507d08" /> + +<p><em>Last historical dataset collected during two weeks ending on November 1, 2010</em></p>  </div><!-- end dashboard-panel --> diff --git a/docs/html/resources/faq/framework.jd b/docs/html/resources/faq/framework.jd index f4b8db086222..4a7a3fc20e66 100644 --- a/docs/html/resources/faq/framework.jd +++ b/docs/html/resources/faq/framework.jd @@ -68,12 +68,17 @@ Preferences</a> storage mechanism.</p>  <p>For sharing complex non-persistent user-defined objects for short  duration, the following approaches are recommended:  </p> -  <h4>The android.app.Application class</h4> -  <p>The android.app.Application is a base class for those who need to -maintain global application state. It can be accessed via -getApplication() from any Activity or Service. It has a couple of -life-cycle methods and will be instantiated by Android automatically if -your register it in AndroidManifest.xml.</p> +  <h4>Singleton class</h4> +  <p>You can take advantage of the fact that your application +components run in the same process through the use of a singleton. +This is a class that is designed to have only one instance.  It +has a static method with a name such as <code>getInstance()</code> +that returns the instance; the first time this method is called, +it creates the global instance.  Because all callers get the same +instance, they can use this as a point of interaction.  For +example activity A may retrieve the instance and call setValue(3); +later activity B may retrieve the instance and call getValue() to +retrieve the last set value.</p>    <h4>A public static field/method</h4>    <p>An alternate way to make data accessible across Activities/Services is to use <em>public static</em> @@ -90,18 +95,6 @@ Long based on a counter or time stamp) to the recipient activity via  intent extras. The recipient activity retrieves the object using this  key.</p> -  <h4>A Singleton class</h4> -  <p>There are advantages to using a static Singleton, such as you can -refer to them without casting getApplication() to an -application-specific class, or going to the trouble of hanging an -interface on all your Application subclasses so that your various -modules can refer to that interface instead. </p> -<p>But, the life cycle of a static is not well under your control; so -to abide by the life-cycle model, the application class should initiate and -tear down these static objects in the onCreate() and onTerminate() methods -of the Application Class</p> -</p> -  <h3>Persistent Objects</h3>  <p>Even while an application appears to continue running, the system @@ -146,15 +139,11 @@ call.</p>  <h2>If an Activity starts a remote service, is there any way for the  Service to pass a message back to the Activity?</h2> -<p>The remote service can define a callback interface and register it with the -clients to callback into the clients. The  -{@link android.os.RemoteCallbackList RemoteCallbackList} class provides methods to -register and unregister clients with the service, and send and receive -messages.</p> - -<p>The sample code for remote service callbacks is given in <a -href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">ApiDemos/RemoteService</a></p> - +<p>See the {@link android.app.Service} documentation's for examples of +how clients can interact with a service.  You can take advantage of the +fact that your components run in the same process to greatly simplify +service interaction from the generic remote case, as shown by the "Local +Service Sample".  In some cases techniques like singletons may also make sense.  <a name="6" id="6"></a> diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index a25fad4d349d..289348a29222 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -51,7 +51,7 @@ public class ColorDrawable extends Drawable {       */      public ColorDrawable(int color) {          this(null); -        mState.mBaseColor = mState.mUseColor = color; +        setColor(color);      }      private ColorDrawable(ColorState state) { @@ -72,6 +72,25 @@ public class ColorDrawable extends Drawable {      }      /** +     * Gets the drawable's color value. +     * +     * @return int The color to draw. +     */ +    public int getColor() { +        return mState.mUseColor; +    } + +    /** +     * Sets the drawable's color value. This action will clobber the results of prior calls to +     * {@link #setAlpha(int)} on this object, which side-affected the underlying color. +     * +     * @param color The color to draw. +     */ +    public void setColor(int color) { +        mState.mBaseColor = mState.mUseColor = color; +    } + +    /**       * Returns the alpha value of this drawable's color.       *       * @return A value between 0 and 255. @@ -131,7 +150,7 @@ public class ColorDrawable extends Drawable {      }      final static class ColorState extends ConstantState { -        int mBaseColor; // initial color. never changes +        int mBaseColor; // base color, independent of setAlpha()          int mUseColor;  // basecolor modulated by setAlpha()          int mChangingConfigurations; diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java index f8ad5cc17537..dfd6ac8a6605 100644 --- a/graphics/java/android/renderscript/Allocation.java +++ b/graphics/java/android/renderscript/Allocation.java @@ -199,6 +199,7 @@ public class Allocation extends BaseObj {              throw new IllegalStateException("Resize only support for 1D allocations at this time.");          }          mRS.nAllocationResize1D(mID, dimX); +        mRS.finish();  // Necessary because resize is fifoed and update is async.          int typeID = mRS.nAllocationGetType(mID);          mType = new Type(typeID, mRS); diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index 1f5ed7cf367d..c692bc1e9978 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -78,10 +78,6 @@ void ScriptC::setupScript(Context *rsc)          if (dest) {              *dest = ptr; -        } else { -            if (rsc->props.mLogScripts) { -                LOGV("ScriptC::setupScript, NULL var binding address."); -            }          }      }  } @@ -404,16 +400,14 @@ static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name)      const ScriptCState::SymbolTable_t *sym;      ScriptC *s = (ScriptC *)pContext;      sym = ScriptCState::lookupSymbol(name); -    if (sym) { -        return sym->mPtr; +    if (!sym) { +        sym = ScriptCState::lookupSymbolCL(name);      } -    sym = ScriptCState::lookupSymbolCL(name); -    if (sym) { -        return sym->mPtr; +    if (!sym) { +        sym = ScriptCState::lookupSymbolGL(name);      } -    s->mEnviroment.mIsThreadable = false; -    sym = ScriptCState::lookupSymbolGL(name);      if (sym) { +        s->mEnviroment.mIsThreadable &= sym->threadable;          return sym->mPtr;      }      LOGE("ScriptC sym lookup failed for %s", name); @@ -425,7 +419,6 @@ extern unsigned rs_runtime_lib_bc_size;  void ScriptCState::runCompiler(Context *rsc, ScriptC *s)  { -    LOGV("%p ScriptCState::runCompiler ", rsc);      {          StopWatch compileTimer("RenderScript compile time");          s->mBccScript = bccCreateScript(); diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h index e5b5ba9f8933..86a7ad3ea244 100644 --- a/libs/rs/rsScriptC.h +++ b/libs/rs/rsScriptC.h @@ -89,6 +89,7 @@ public:      struct SymbolTable_t {          const char * mName;          void * mPtr; +        bool threadable;      };      //static SymbolTable_t gSyms[];      static const SymbolTable_t * lookupSymbol(const char *); diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp index 9fadee0f1af1..ecae306e8a75 100644 --- a/libs/rs/rsScriptC_Lib.cpp +++ b/libs/rs/rsScriptC_Lib.cpp @@ -436,120 +436,120 @@ void SC_ForEach2(RsScript vs,  //                 ::= d  # double  static ScriptCState::SymbolTable_t gSyms[] = { -    { "__divsi3", (void *)&SC_divsi3 }, +    { "__divsi3", (void *)&SC_divsi3, true },      // allocation -    { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX }, -    { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY }, -    { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ }, -    { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD }, -    { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces }, -    { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation }, +    { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX, true }, +    { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY, true }, +    { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ, true }, +    { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD, true }, +    { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces, true }, +    { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation, true }, -    { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX }, -    { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY }, -    { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ }, +    { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX, true }, +    { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true }, +    { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true }, -    { "_Z11rsSetObjectP10rs_elementS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP10rs_element", (void *)&SC_clearObject }, -    { "_Z10rsIsObject10rs_element", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP10rs_elementS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP10rs_element", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject10rs_element", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP7rs_typeS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP7rs_type", (void *)&SC_clearObject }, -    { "_Z10rsIsObject7rs_type", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP7rs_typeS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP7rs_type", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject7rs_type", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP13rs_allocationS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP13rs_allocation", (void *)&SC_clearObject }, -    { "_Z10rsIsObject13rs_allocation", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP13rs_allocationS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP13rs_allocation", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject13rs_allocation", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP10rs_samplerS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP10rs_sampler", (void *)&SC_clearObject }, -    { "_Z10rsIsObject10rs_sampler", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP10rs_samplerS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP10rs_sampler", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject10rs_sampler", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP9rs_scriptS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP9rs_script", (void *)&SC_clearObject }, -    { "_Z10rsIsObject9rs_script", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP9rs_scriptS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP9rs_script", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject9rs_script", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_clearObject }, -    { "_Z10rsIsObject7rs_mesh", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject7rs_mesh", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP19rs_program_fragment", (void *)&SC_clearObject }, -    { "_Z10rsIsObject19rs_program_fragment", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP19rs_program_fragment", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject19rs_program_fragment", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP17rs_program_vertex", (void *)&SC_clearObject }, -    { "_Z10rsIsObject17rs_program_vertex", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP17rs_program_vertex", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject17rs_program_vertex", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP17rs_program_raster", (void *)&SC_clearObject }, -    { "_Z10rsIsObject17rs_program_raster", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP17rs_program_raster", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject17rs_program_raster", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP16rs_program_store", (void *)&SC_clearObject }, -    { "_Z10rsIsObject16rs_program_store", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP16rs_program_store", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject16rs_program_store", (void *)&SC_isObject, true }, -    { "_Z11rsSetObjectP7rs_fontS_", (void *)&SC_setObject }, -    { "_Z13rsClearObjectP7rs_font", (void *)&SC_clearObject }, -    { "_Z10rsIsObject7rs_font", (void *)&SC_isObject }, +    { "_Z11rsSetObjectP7rs_fontS_", (void *)&SC_setObject, true }, +    { "_Z13rsClearObjectP7rs_font", (void *)&SC_clearObject, true }, +    { "_Z10rsIsObject7rs_font", (void *)&SC_isObject, true }, -    { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty }, +    { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty, true },      // Debug -    { "_Z7rsDebugPKcf", (void *)&SC_debugF }, -    { "_Z7rsDebugPKcff", (void *)&SC_debugFv2 }, -    { "_Z7rsDebugPKcfff", (void *)&SC_debugFv3 }, -    { "_Z7rsDebugPKcffff", (void *)&SC_debugFv4 }, -    { "_Z7rsDebugPKcd", (void *)&SC_debugD }, -    { "_Z7rsDebugPKcPK12rs_matrix4x4", (void *)&SC_debugFM4v4 }, -    { "_Z7rsDebugPKcPK12rs_matrix3x3", (void *)&SC_debugFM3v3 }, -    { "_Z7rsDebugPKcPK12rs_matrix2x2", (void *)&SC_debugFM2v2 }, -    { "_Z7rsDebugPKci", (void *)&SC_debugI32 }, -    { "_Z7rsDebugPKcj", (void *)&SC_debugU32 }, +    { "_Z7rsDebugPKcf", (void *)&SC_debugF, true }, +    { "_Z7rsDebugPKcff", (void *)&SC_debugFv2, true }, +    { "_Z7rsDebugPKcfff", (void *)&SC_debugFv3, true }, +    { "_Z7rsDebugPKcffff", (void *)&SC_debugFv4, true }, +    { "_Z7rsDebugPKcd", (void *)&SC_debugD, true }, +    { "_Z7rsDebugPKcPK12rs_matrix4x4", (void *)&SC_debugFM4v4, true }, +    { "_Z7rsDebugPKcPK12rs_matrix3x3", (void *)&SC_debugFM3v3, true }, +    { "_Z7rsDebugPKcPK12rs_matrix2x2", (void *)&SC_debugFM2v2, true }, +    { "_Z7rsDebugPKci", (void *)&SC_debugI32, true }, +    { "_Z7rsDebugPKcj", (void *)&SC_debugU32, true },      // Both "long" and "unsigned long" need to be redirected to their      // 64-bit counterparts, since we have hacked Slang to use 64-bit      // for "long" on Arm (to be similar to Java). -    { "_Z7rsDebugPKcl", (void *)&SC_debugLL64 }, -    { "_Z7rsDebugPKcm", (void *)&SC_debugULL64 }, -    { "_Z7rsDebugPKcx", (void *)&SC_debugLL64 }, -    { "_Z7rsDebugPKcy", (void *)&SC_debugULL64 }, -    { "_Z7rsDebugPKcPKv", (void *)&SC_debugP }, +    { "_Z7rsDebugPKcl", (void *)&SC_debugLL64, true }, +    { "_Z7rsDebugPKcm", (void *)&SC_debugULL64, true }, +    { "_Z7rsDebugPKcx", (void *)&SC_debugLL64, true }, +    { "_Z7rsDebugPKcy", (void *)&SC_debugULL64, true }, +    { "_Z7rsDebugPKcPKv", (void *)&SC_debugP, true },      // RS Math -    { "_Z6rsRandi", (void *)&SC_randi }, -    { "_Z6rsRandii", (void *)&SC_randi2 }, -    { "_Z6rsRandf", (void *)&SC_randf }, -    { "_Z6rsRandff", (void *)&SC_randf2 }, -    { "_Z6rsFracf", (void *)&SC_frac }, +    { "_Z6rsRandi", (void *)&SC_randi, true }, +    { "_Z6rsRandii", (void *)&SC_randi2, true }, +    { "_Z6rsRandf", (void *)&SC_randf, true }, +    { "_Z6rsRandff", (void *)&SC_randf2, true }, +    { "_Z6rsFracf", (void *)&SC_frac, true },      // time -    { "_Z8rsSecondv", (void *)&SC_second }, -    { "_Z8rsMinutev", (void *)&SC_minute }, -    { "_Z6rsHourv", (void *)&SC_hour }, -    { "_Z5rsDayv", (void *)&SC_day }, -    { "_Z7rsMonthv", (void *)&SC_month }, -    { "_Z6rsYearv", (void *)&SC_year }, -    { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis }, -    { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos }, -    { "_Z7rsGetDtv", (void*)&SC_getDt }, - -    { "_Z14rsSendToClienti", (void *)&SC_toClient }, -    { "_Z14rsSendToClientiPKvj", (void *)&SC_toClient2 }, -    { "_Z22rsSendToClientBlockingi", (void *)&SC_toClientBlocking }, -    { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_toClientBlocking2 }, - -    { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach }, -    //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2 }, +    { "_Z8rsSecondv", (void *)&SC_second, true }, +    { "_Z8rsMinutev", (void *)&SC_minute, true }, +    { "_Z6rsHourv", (void *)&SC_hour, true }, +    { "_Z5rsDayv", (void *)&SC_day, true }, +    { "_Z7rsMonthv", (void *)&SC_month, true }, +    { "_Z6rsYearv", (void *)&SC_year, true }, +    { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true }, +    { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true }, +    { "_Z7rsGetDtv", (void*)&SC_getDt, false }, + +    { "_Z14rsSendToClienti", (void *)&SC_toClient, false }, +    { "_Z14rsSendToClientiPKvj", (void *)&SC_toClient2, false }, +    { "_Z22rsSendToClientBlockingi", (void *)&SC_toClientBlocking, false }, +    { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_toClientBlocking2, false }, + +    { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false }, +    //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, true },  //////////////////////////////////////////////////////////////////// -    //{ "sinf_fast", (void *)&SC_sinf_fast }, -    //{ "cosf_fast", (void *)&SC_cosf_fast }, +    //{ "sinf_fast", (void *)&SC_sinf_fast, true }, +    //{ "cosf_fast", (void *)&SC_cosf_fast, true }, -    { NULL, NULL } +    { NULL, NULL, false }  };  const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) diff --git a/libs/rs/rsScriptC_LibCL.cpp b/libs/rs/rsScriptC_LibCL.cpp index 1b1a7529031e..7031f84942bc 100644 --- a/libs/rs/rsScriptC_LibCL.cpp +++ b/libs/rs/rsScriptC_LibCL.cpp @@ -88,11 +88,6 @@ static float SC_tanpi(float v) {      return tanf(v * M_PI);  } -    //{ "logb", (void *)& }, -    //{ "mad", (void *)& }, -    //{ "nan", (void *)& }, -    //{ "tgamma", (void *)& }, -  //////////////////////////////////////////////////////////////////////////////  // Integer  ////////////////////////////////////////////////////////////////////////////// @@ -198,105 +193,105 @@ static float SC_sign_f32(float value)  static ScriptCState::SymbolTable_t gSyms[] = {      // OpenCL math -    { "_Z4acosf", (void *)&acosf }, -    { "_Z5acoshf", (void *)&acoshf }, -    { "_Z6acospif", (void *)&SC_acospi }, -    { "_Z4asinf", (void *)&asinf }, -    { "_Z5asinhf", (void *)&asinhf }, -    { "_Z6asinpif", (void *)&SC_asinpi }, -    { "_Z4atanf", (void *)&atanf }, -    { "_Z5atan2ff", (void *)&atan2f }, -    { "_Z6atanpif", (void *)&SC_atanpi }, -    { "_Z7atan2piff", (void *)&SC_atan2pi }, -    { "_Z4cbrtf", (void *)&cbrtf }, -    { "_Z4ceilf", (void *)&ceilf }, -    { "_Z8copysignff", (void *)©signf }, -    { "_Z3cosf", (void *)&cosf }, -    { "_Z4coshf", (void *)&coshf }, -    { "_Z5cospif", (void *)&SC_cospi }, -    { "_Z4erfcf", (void *)&erfcf }, -    { "_Z3erff", (void *)&erff }, -    { "_Z3expf", (void *)&expf }, -    { "_Z4exp2f", (void *)&exp2f }, -    { "_Z5exp10f", (void *)&SC_exp10 }, -    { "_Z5expm1f", (void *)&expm1f }, -    { "_Z4fabsf", (void *)&fabsf }, -    { "_Z4fdimff", (void *)&fdimf }, -    { "_Z5floorf", (void *)&floorf }, -    { "_Z3fmafff", (void *)&fmaf }, -    { "_Z4fmaxff", (void *)&fmaxf }, -    { "_Z4fminff", (void *)&fminf },  // float fmin(float, float) -    { "_Z4fmodff", (void *)&fmodf }, -    { "_Z5fractfPf", (void *)&SC_fract }, -    { "_Z5frexpfPi", (void *)&frexpf }, -    { "_Z5hypotff", (void *)&hypotf }, -    { "_Z5ilogbf", (void *)&ilogbf }, -    { "_Z5ldexpfi", (void *)&ldexpf }, -    { "_Z6lgammaf", (void *)&lgammaf }, -    { "_Z3logf", (void *)&logf }, -    { "_Z4log2f", (void *)&SC_log2 }, -    { "_Z5log10f", (void *)&log10f }, -    { "_Z5log1pf", (void *)&log1pf }, -    //{ "logb", (void *)& }, -    //{ "mad", (void *)& }, -    { "modf", (void *)&modff }, -    //{ "nan", (void *)& }, -    { "_Z9nextafterff", (void *)&nextafterf }, -    { "_Z3powff", (void *)&powf }, -    { "_Z4pownfi", (void *)&SC_pown }, -    { "_Z4powrff", (void *)&SC_powr }, -    { "_Z9remainderff", (void *)&remainderf }, -    { "remquo", (void *)&remquof }, -    { "_Z4rintf", (void *)&rintf }, -    { "_Z5rootnfi", (void *)&SC_rootn }, -    { "_Z5roundf", (void *)&roundf }, -    { "_Z5rsqrtf", (void *)&SC_rsqrt }, -    { "_Z3sinf", (void *)&sinf }, -    { "sincos", (void *)&SC_sincos }, -    { "_Z4sinhf", (void *)&sinhf }, -    { "_Z5sinpif", (void *)&SC_sinpi }, -    { "_Z4sqrtf", (void *)&sqrtf }, -    { "_Z3tanf", (void *)&tanf }, -    { "_Z4tanhf", (void *)&tanhf }, -    { "_Z5tanpif", (void *)&SC_tanpi }, -    //{ "tgamma", (void *)& }, -    { "_Z5truncf", (void *)&truncf }, +    { "_Z4acosf", (void *)&acosf, true }, +    { "_Z5acoshf", (void *)&acoshf, true }, +    { "_Z6acospif", (void *)&SC_acospi, true }, +    { "_Z4asinf", (void *)&asinf, true }, +    { "_Z5asinhf", (void *)&asinhf, true }, +    { "_Z6asinpif", (void *)&SC_asinpi, true }, +    { "_Z4atanf", (void *)&atanf, true }, +    { "_Z5atan2ff", (void *)&atan2f, true }, +    { "_Z6atanpif", (void *)&SC_atanpi, true }, +    { "_Z7atan2piff", (void *)&SC_atan2pi, true }, +    { "_Z4cbrtf", (void *)&cbrtf, true }, +    { "_Z4ceilf", (void *)&ceilf, true }, +    { "_Z8copysignff", (void *)©signf, true }, +    { "_Z3cosf", (void *)&cosf, true }, +    { "_Z4coshf", (void *)&coshf, true }, +    { "_Z5cospif", (void *)&SC_cospi, true }, +    { "_Z4erfcf", (void *)&erfcf, true }, +    { "_Z3erff", (void *)&erff, true }, +    { "_Z3expf", (void *)&expf, true }, +    { "_Z4exp2f", (void *)&exp2f, true }, +    { "_Z5exp10f", (void *)&SC_exp10, true }, +    { "_Z5expm1f", (void *)&expm1f, true }, +    { "_Z4fabsf", (void *)&fabsf, true }, +    { "_Z4fdimff", (void *)&fdimf, true }, +    { "_Z5floorf", (void *)&floorf, true }, +    { "_Z3fmafff", (void *)&fmaf, true }, +    { "_Z4fmaxff", (void *)&fmaxf, true }, +    { "_Z4fminff", (void *)&fminf, true },  // float fmin(float, float) +    { "_Z4fmodff", (void *)&fmodf, true }, +    { "_Z5fractfPf", (void *)&SC_fract, true }, +    { "_Z5frexpfPi", (void *)&frexpf, true }, +    { "_Z5hypotff", (void *)&hypotf, true }, +    { "_Z5ilogbf", (void *)&ilogbf, true }, +    { "_Z5ldexpfi", (void *)&ldexpf, true }, +    { "_Z6lgammaf", (void *)&lgammaf, true }, +    { "_Z3logf", (void *)&logf, true }, +    { "_Z4log2f", (void *)&SC_log2, true }, +    { "_Z5log10f", (void *)&log10f, true }, +    { "_Z5log1pf", (void *)&log1pf, true }, +    //{ "logb", (void *)&, true }, +    //{ "mad", (void *)&, true }, +    { "modf", (void *)&modff, true }, +    //{ "nan", (void *)&, true }, +    { "_Z9nextafterff", (void *)&nextafterf, true }, +    { "_Z3powff", (void *)&powf, true }, +    { "_Z4pownfi", (void *)&SC_pown, true }, +    { "_Z4powrff", (void *)&SC_powr, true }, +    { "_Z9remainderff", (void *)&remainderf, true }, +    { "remquo", (void *)&remquof, true }, +    { "_Z4rintf", (void *)&rintf, true }, +    { "_Z5rootnfi", (void *)&SC_rootn, true }, +    { "_Z5roundf", (void *)&roundf, true }, +    { "_Z5rsqrtf", (void *)&SC_rsqrt, true }, +    { "_Z3sinf", (void *)&sinf, true }, +    { "sincos", (void *)&SC_sincos, true }, +    { "_Z4sinhf", (void *)&sinhf, true }, +    { "_Z5sinpif", (void *)&SC_sinpi, true }, +    { "_Z4sqrtf", (void *)&sqrtf, true }, +    { "_Z3tanf", (void *)&tanf, true }, +    { "_Z4tanhf", (void *)&tanhf, true }, +    { "_Z5tanpif", (void *)&SC_tanpi, true }, +    //{ "tgamma", (void *)&, true }, +    { "_Z5truncf", (void *)&truncf, true },      // OpenCL Int -    { "_Z3absi", (void *)&SC_abs_i32 }, -    { "_Z3abss", (void *)&SC_abs_i16 }, -    { "_Z3absc", (void *)&SC_abs_i8 }, -    { "_Z3clzj", (void *)&SC_clz_u32 }, -    { "_Z3clzt", (void *)&SC_clz_u16 }, -    { "_Z3clzh", (void *)&SC_clz_u8 }, -    { "_Z3clzi", (void *)&SC_clz_i32 }, -    { "_Z3clzs", (void *)&SC_clz_i16 }, -    { "_Z3clzc", (void *)&SC_clz_i8 }, -    { "_Z3maxjj", (void *)&SC_max_u32 }, -    { "_Z3maxtt", (void *)&SC_max_u16 }, -    { "_Z3maxhh", (void *)&SC_max_u8 }, -    { "_Z3maxii", (void *)&SC_max_i32 }, -    { "_Z3maxss", (void *)&SC_max_i16 }, -    { "_Z3maxcc", (void *)&SC_max_i8 }, -    { "_Z3minjj", (void *)&SC_min_u32 }, -    { "_Z3mintt", (void *)&SC_min_u16 }, -    { "_Z3minhh", (void *)&SC_min_u8 }, -    { "_Z3minii", (void *)&SC_min_i32 }, -    { "_Z3minss", (void *)&SC_min_i16 }, -    { "_Z3mincc", (void *)&SC_min_i8 }, +    { "_Z3absi", (void *)&SC_abs_i32, true }, +    { "_Z3abss", (void *)&SC_abs_i16, true }, +    { "_Z3absc", (void *)&SC_abs_i8, true }, +    { "_Z3clzj", (void *)&SC_clz_u32, true }, +    { "_Z3clzt", (void *)&SC_clz_u16, true }, +    { "_Z3clzh", (void *)&SC_clz_u8, true }, +    { "_Z3clzi", (void *)&SC_clz_i32, true }, +    { "_Z3clzs", (void *)&SC_clz_i16, true }, +    { "_Z3clzc", (void *)&SC_clz_i8, true }, +    { "_Z3maxjj", (void *)&SC_max_u32, true }, +    { "_Z3maxtt", (void *)&SC_max_u16, true }, +    { "_Z3maxhh", (void *)&SC_max_u8, true }, +    { "_Z3maxii", (void *)&SC_max_i32, true }, +    { "_Z3maxss", (void *)&SC_max_i16, true }, +    { "_Z3maxcc", (void *)&SC_max_i8, true }, +    { "_Z3minjj", (void *)&SC_min_u32, true }, +    { "_Z3mintt", (void *)&SC_min_u16, true }, +    { "_Z3minhh", (void *)&SC_min_u8, true }, +    { "_Z3minii", (void *)&SC_min_i32, true }, +    { "_Z3minss", (void *)&SC_min_i16, true }, +    { "_Z3mincc", (void *)&SC_min_i8, true },      // OpenCL 6.11.4 -    { "_Z5clampfff", (void *)&SC_clamp_f32 }, -    { "_Z7degreesf", (void *)&SC_degrees }, -    { "_Z3maxff", (void *)&SC_max_f32 }, -    { "_Z3minff", (void *)&SC_min_f32 }, -    { "_Z3mixfff", (void *)&SC_mix_f32 }, -    { "_Z7radiansf", (void *)&SC_radians }, -    { "_Z4stepff", (void *)&SC_step_f32 }, -    //{ "smoothstep", (void *)& }, -    { "_Z4signf", (void *)&SC_sign_f32 }, - -    { NULL, NULL } +    { "_Z5clampfff", (void *)&SC_clamp_f32, true }, +    { "_Z7degreesf", (void *)&SC_degrees, true }, +    { "_Z3maxff", (void *)&SC_max_f32, true }, +    { "_Z3minff", (void *)&SC_min_f32, true }, +    { "_Z3mixfff", (void *)&SC_mix_f32, true }, +    { "_Z7radiansf", (void *)&SC_radians, true }, +    { "_Z4stepff", (void *)&SC_step_f32, true }, +    //{ "smoothstep", (void *)&, true }, +    { "_Z4signf", (void *)&SC_sign_f32, true }, + +    { NULL, NULL, false }  };  const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbolCL(const char *sym) diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp index b991cab7b7f8..5b07e7bdd7a2 100644 --- a/libs/rs/rsScriptC_LibGL.cpp +++ b/libs/rs/rsScriptC_LibGL.cpp @@ -441,53 +441,53 @@ static void SC_FontColor(float r, float g, float b, float a)  //                 ::= d  # double  static ScriptCState::SymbolTable_t gSyms[] = { -    { "_Z22rsgBindProgramFragment19rs_program_fragment", (void *)&SC_bindProgramFragment }, -    { "_Z19rsgBindProgramStore16rs_program_store", (void *)&SC_bindProgramStore }, -    { "_Z20rsgBindProgramVertex17rs_program_vertex", (void *)&SC_bindProgramVertex }, -    { "_Z20rsgBindProgramRaster17rs_program_raster", (void *)&SC_bindProgramRaster }, -    { "_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler", (void *)&SC_bindSampler }, -    { "_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation", (void *)&SC_bindTexture }, +    { "_Z22rsgBindProgramFragment19rs_program_fragment", (void *)&SC_bindProgramFragment, false }, +    { "_Z19rsgBindProgramStore16rs_program_store", (void *)&SC_bindProgramStore, false }, +    { "_Z20rsgBindProgramVertex17rs_program_vertex", (void *)&SC_bindProgramVertex, false }, +    { "_Z20rsgBindProgramRaster17rs_program_raster", (void *)&SC_bindProgramRaster, false }, +    { "_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler", (void *)&SC_bindSampler, false }, +    { "_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation", (void *)&SC_bindTexture, false }, -    { "_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadProjectionMatrix }, -    { "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadModelMatrix }, -    { "_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadTextureMatrix }, +    { "_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadProjectionMatrix, false }, +    { "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadModelMatrix, false }, +    { "_Z33rsgProgramVertexLoadTextureMatrixPK12rs_matrix4x4", (void *)&SC_vpLoadTextureMatrix, false }, -    { "_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4", (void *)&SC_vpGetProjectionMatrix }, +    { "_Z35rsgProgramVertexGetProjectionMatrixP12rs_matrix4x4", (void *)&SC_vpGetProjectionMatrix, false }, -    { "_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff", (void *)&SC_pfConstantColor }, +    { "_Z31rsgProgramFragmentConstantColor19rs_program_fragmentffff", (void *)&SC_pfConstantColor, false }, -    { "_Z11rsgGetWidthv", (void *)&SC_getWidth }, -    { "_Z12rsgGetHeightv", (void *)&SC_getHeight }, +    { "_Z11rsgGetWidthv", (void *)&SC_getWidth, false }, +    { "_Z12rsgGetHeightv", (void *)&SC_getHeight, false }, -    { "_Z18rsgUploadToTexture13rs_allocationj", (void *)&SC_uploadToTexture2 }, -    { "_Z18rsgUploadToTexture13rs_allocation", (void *)&SC_uploadToTexture }, -    { "_Z23rsgUploadToBufferObject13rs_allocation", (void *)&SC_uploadToBufferObject }, +    { "_Z18rsgUploadToTexture13rs_allocationj", (void *)&SC_uploadToTexture2, false }, +    { "_Z18rsgUploadToTexture13rs_allocation", (void *)&SC_uploadToTexture, false }, +    { "_Z23rsgUploadToBufferObject13rs_allocation", (void *)&SC_uploadToBufferObject, false }, -    { "_Z11rsgDrawRectfffff", (void *)&SC_drawRect }, -    { "_Z11rsgDrawQuadffffffffffff", (void *)&SC_drawQuad }, -    { "_Z20rsgDrawQuadTexCoordsffffffffffffffffffff", (void *)&SC_drawQuadTexCoords }, -    { "_Z24rsgDrawSpriteScreenspacefffff", (void *)&SC_drawSpriteScreenspace }, +    { "_Z11rsgDrawRectfffff", (void *)&SC_drawRect, false }, +    { "_Z11rsgDrawQuadffffffffffff", (void *)&SC_drawQuad, false }, +    { "_Z20rsgDrawQuadTexCoordsffffffffffffffffffff", (void *)&SC_drawQuadTexCoords, false }, +    { "_Z24rsgDrawSpriteScreenspacefffff", (void *)&SC_drawSpriteScreenspace, false }, -    { "_Z11rsgDrawMesh7rs_mesh", (void *)&SC_drawMesh }, -    { "_Z11rsgDrawMesh7rs_meshj", (void *)&SC_drawMeshPrimitive }, -    { "_Z11rsgDrawMesh7rs_meshjjj", (void *)&SC_drawMeshPrimitiveRange }, -    { "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_", (void *)&SC_meshComputeBoundingBox }, +    { "_Z11rsgDrawMesh7rs_mesh", (void *)&SC_drawMesh, false }, +    { "_Z11rsgDrawMesh7rs_meshj", (void *)&SC_drawMeshPrimitive, false }, +    { "_Z11rsgDrawMesh7rs_meshjjj", (void *)&SC_drawMeshPrimitiveRange, false }, +    { "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_", (void *)&SC_meshComputeBoundingBox, false }, -    { "_Z13rsgClearColorffff", (void *)&SC_ClearColor }, -    { "_Z13rsgClearDepthf", (void *)&SC_ClearDepth }, +    { "_Z13rsgClearColorffff", (void *)&SC_ClearColor, false }, +    { "_Z13rsgClearDepthf", (void *)&SC_ClearDepth, false }, -    { "_Z11rsgDrawTextPKcii", (void *)&SC_DrawText }, -    { "_Z11rsgDrawText13rs_allocationii", (void *)&SC_DrawTextAlloc }, -    { "_Z14rsgMeasureTextPKcPiS1_S1_S1_", (void *)&SC_MeasureText }, -    { "_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_", (void *)&SC_MeasureTextAlloc }, +    { "_Z11rsgDrawTextPKcii", (void *)&SC_DrawText, false }, +    { "_Z11rsgDrawText13rs_allocationii", (void *)&SC_DrawTextAlloc, false }, +    { "_Z14rsgMeasureTextPKcPiS1_S1_S1_", (void *)&SC_MeasureText, false }, +    { "_Z14rsgMeasureText13rs_allocationPiS0_S0_S0_", (void *)&SC_MeasureTextAlloc, false }, -    { "_Z11rsgBindFont7rs_font", (void *)&SC_BindFont }, -    { "_Z12rsgFontColorffff", (void *)&SC_FontColor }, +    { "_Z11rsgBindFont7rs_font", (void *)&SC_BindFont, false }, +    { "_Z12rsgFontColorffff", (void *)&SC_FontColor, false },      // misc -    { "_Z5colorffff", (void *)&SC_color }, +    { "_Z5colorffff", (void *)&SC_color, false }, -    { NULL, NULL } +    { NULL, NULL, false }  };  const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbolGL(const char *sym) diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index b936c4d47044..58d4c568c1fe 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -1408,8 +1408,13 @@ String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication*  void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {      int32_t eventType = POWER_MANAGER_BUTTON_EVENT; -    if (eventEntry->type == EventEntry::TYPE_MOTION) { +    switch (eventEntry->type) { +    case EventEntry::TYPE_MOTION: {          const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry); +        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) { +            return; +        } +          if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {              switch (motionEntry->action) {              case AMOTION_EVENT_ACTION_DOWN: @@ -1427,6 +1432,15 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {                  break;              }          } +        break; +    } +    case EventEntry::TYPE_KEY: { +        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry); +        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) { +            return; +        } +        break; +    }      }      CommandEntry* commandEntry = postCommandLocked( diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 381b77a2c8cd..532a2dfb162d 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -83,6 +83,11 @@ public class MediaFile {      private static final int FIRST_PLAYLIST_FILE_TYPE = FILE_TYPE_M3U;      private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_WPL; +    // Drm file types +    public static final int FILE_TYPE_FL      = 51; +    private static final int FIRST_DRM_FILE_TYPE = FILE_TYPE_FL; +    private static final int LAST_DRM_FILE_TYPE = FILE_TYPE_FL; +      // Other popular file types      public static final int FILE_TYPE_TEXT          = 100;      public static final int FILE_TYPE_HTML          = 101; @@ -189,6 +194,8 @@ public class MediaFile {          addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls", MtpConstants.FORMAT_PLS_PLAYLIST);          addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl", MtpConstants.FORMAT_WPL_PLAYLIST); +        addFileType("FL", FILE_TYPE_FL, "application/x-android-drm-fl"); +          addFileType("TXT", FILE_TYPE_TEXT, "text/plain", MtpConstants.FORMAT_TEXT);          addFileType("HTM", FILE_TYPE_HTML, "text/html", MtpConstants.FORMAT_HTML);          addFileType("HTML", FILE_TYPE_HTML, "text/html", MtpConstants.FORMAT_HTML); @@ -222,6 +229,11 @@ public class MediaFile {                  fileType <= LAST_PLAYLIST_FILE_TYPE);      } +    public static boolean isDrmFileType(int fileType) { +        return (fileType >= FIRST_DRM_FILE_TYPE && +                fileType <= LAST_DRM_FILE_TYPE); +    } +      public static MediaFileType getFileType(String path) {          int lastDot = path.lastIndexOf(".");          if (lastDot < 0) diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index e5fa0f823a2f..5aabddf0a24e 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -26,6 +26,7 @@ import android.content.Context;  import android.content.IContentProvider;  import android.database.Cursor;  import android.database.SQLException; +import android.drm.DrmManagerClient;  import android.graphics.BitmapFactory;  import android.net.Uri;  import android.os.Process; @@ -360,6 +361,7 @@ public class MediaScanner      private ArrayList<FileCacheEntry> mPlayLists;      private HashMap<String, Uri> mGenreCache; +    private DrmManagerClient mDrmManagerClient = null;      public MediaScanner(Context c) {          native_setup(); @@ -447,6 +449,11 @@ public class MediaScanner                  }              } +            if (System.getProperty("drm.service.enabled").equals("true") +                    && MediaFile.isDrmFileType(mFileType)) { +                mFileType = getFileTypeFromDrm(path); +            } +              String key = path;              if (mCaseInsensitivePaths) {                  key = path.toLowerCase(); @@ -874,6 +881,27 @@ public class MediaScanner              }          } +        private int getFileTypeFromDrm(String path) { +            if (!System.getProperty("drm.service.enabled").equals("true")) { +                return 0; +            } + +            int resultFileType = 0; + +            if (mDrmManagerClient == null) { +                mDrmManagerClient = new DrmManagerClient(mContext); +            } + +            if (mDrmManagerClient.canHandle(path, null)) { +                String drmMimetype = mDrmManagerClient.getOriginalMimeType(path); +                if (drmMimetype != null) { +                    mMimeType = drmMimetype; +                    resultFileType = MediaFile.getFileTypeForMimeType(drmMimetype); +                } +            } +            return resultFileType; +        } +      }; // end of anonymous MediaScannerClient instance      private void prescan(String filePath, boolean prescanFiles) throws RemoteException { diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java index 51647434e269..57ab3a1f6375 100644 --- a/media/java/android/media/MtpDatabase.java +++ b/media/java/android/media/MtpDatabase.java @@ -23,6 +23,7 @@ import android.content.Intent;  import android.database.Cursor;  import android.database.sqlite.SQLiteDatabase;  import android.net.Uri; +import android.os.Environment;  import android.os.RemoteException;  import android.provider.MediaStore.Audio;  import android.provider.MediaStore.Files; @@ -45,6 +46,7 @@ public class MtpDatabase {      private final String mVolumeName;      private final Uri mObjectsUri;      private final String mMediaStoragePath; +    private final String mExternalStoragePath;      // true if the database has been modified in the current MTP session      private boolean mDatabaseModified; @@ -77,7 +79,6 @@ public class MtpDatabase {              Files.FileColumns.DATE_MODIFIED, // 5      };      private static final String ID_WHERE = Files.FileColumns._ID + "=?"; -    private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";      private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";      private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "                                              + Files.FileColumns.FORMAT + "=?"; @@ -98,6 +99,7 @@ public class MtpDatabase {          mMediaProvider = context.getContentResolver().acquireProvider("media");          mVolumeName = volumeName;          mMediaStoragePath = storagePath; +        mExternalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();          mObjectsUri = Files.getMtpObjectsUri(volumeName);          mMediaScanner = new MediaScanner(context);          openDevicePropertiesDatabase(context); @@ -112,6 +114,16 @@ public class MtpDatabase {          }      } +    private String externalToMediaPath(String path) { +        // convert external storage path to media path +        if (path != null && mMediaStoragePath != null +                && mExternalStoragePath != null +                && path.startsWith(mExternalStoragePath)) { +            path = mMediaStoragePath + path.substring(mExternalStoragePath.length()); +        } +        return path; +    } +      private void openDevicePropertiesDatabase(Context context) {          mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);          int version = mDevicePropDb.getVersion(); @@ -482,7 +494,7 @@ public class MtpDatabase {          try {              c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null);              if (c != null && c.moveToNext()) { -                path = c.getString(1); +                path = externalToMediaPath(c.getString(1));              }          } catch (RemoteException e) {              Log.e(TAG, "RemoteException in getObjectFilePath", e); @@ -763,7 +775,7 @@ public class MtpDatabase {                  return true;              }          } catch (RemoteException e) { -            Log.e(TAG, "RemoteException in getObjectProperty", e); +            Log.e(TAG, "RemoteException in getObjectInfo", e);          } finally {              if (c != null) {                  c.close(); @@ -786,7 +798,7 @@ public class MtpDatabase {              c = mMediaProvider.query(mObjectsUri, PATH_SIZE_PROJECTION,                              ID_WHERE, new String[] {  Integer.toString(handle) }, null);              if (c != null && c.moveToNext()) { -                String path = c.getString(1); +                String path = externalToMediaPath(c.getString(1));                  path.getChars(0, path.length(), outFilePath, 0);                  outFilePath[path.length()] = 0;                  outFileLength[0] = c.getLong(2); diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index 1629e9f17e98..6c05e03145d6 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -39,7 +39,7 @@ static bool FileHasAcceptableExtension(const char *extension) {          ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",          ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",          ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota", -        ".mkv", ".mka", ".webm", ".ts" +        ".mkv", ".mka", ".webm", ".ts", ".fl"      };      static const size_t kNumValidExtensions =          sizeof(kValidExtensions) / sizeof(kValidExtensions[0]); diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java index 91dc2b26872f..0f1aa4e0ea76 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java @@ -145,7 +145,7 @@ public abstract class KeyguardViewBase extends FrameLayout {                  case KeyEvent.KEYCODE_MEDIA_PLAY:                  case KeyEvent.KEYCODE_MEDIA_PAUSE:                  case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: -                    /* Suppress PLAYPAUSE toggle when phone is ringing or +                    /* Suppress PLAY/PAUSE toggle when phone is ringing or                       * in-call to avoid music playback */                      if (mTelephonyManager == null) {                          mTelephonyManager = (TelephonyManager) getContext().getSystemService( @@ -155,11 +155,13 @@ public abstract class KeyguardViewBase extends FrameLayout {                              mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {                          return true;  // suppress key event                      } -                case KeyEvent.KEYCODE_HEADSETHOOK:  -                case KeyEvent.KEYCODE_MEDIA_STOP:  -                case KeyEvent.KEYCODE_MEDIA_NEXT:  -                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:  -                case KeyEvent.KEYCODE_MEDIA_REWIND:  +                case KeyEvent.KEYCODE_MUTE: +                case KeyEvent.KEYCODE_HEADSETHOOK: +                case KeyEvent.KEYCODE_MEDIA_STOP: +                case KeyEvent.KEYCODE_MEDIA_NEXT: +                case KeyEvent.KEYCODE_MEDIA_PREVIOUS: +                case KeyEvent.KEYCODE_MEDIA_REWIND: +                case KeyEvent.KEYCODE_MEDIA_RECORD:                  case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {                      Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);                      intent.putExtra(Intent.EXTRA_KEY_EVENT, event); @@ -191,12 +193,15 @@ public abstract class KeyguardViewBase extends FrameLayout {          } else if (event.getAction() == KeyEvent.ACTION_UP) {              switch (keyCode) {                  case KeyEvent.KEYCODE_MUTE: -                case KeyEvent.KEYCODE_HEADSETHOOK:  -                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:  -                case KeyEvent.KEYCODE_MEDIA_STOP:  -                case KeyEvent.KEYCODE_MEDIA_NEXT:  -                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:  -                case KeyEvent.KEYCODE_MEDIA_REWIND:  +                case KeyEvent.KEYCODE_HEADSETHOOK: +                case KeyEvent.KEYCODE_MEDIA_PLAY: +                case KeyEvent.KEYCODE_MEDIA_PAUSE: +                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: +                case KeyEvent.KEYCODE_MEDIA_STOP: +                case KeyEvent.KEYCODE_MEDIA_NEXT: +                case KeyEvent.KEYCODE_MEDIA_PREVIOUS: +                case KeyEvent.KEYCODE_MEDIA_REWIND: +                case KeyEvent.KEYCODE_MEDIA_RECORD:                  case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {                      Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);                      intent.putExtra(Intent.EXTRA_KEY_EVENT, event); diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index c034ec9eb3f4..c870503e7674 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -795,6 +795,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,              case KeyEvent.KEYCODE_MEDIA_NEXT:              case KeyEvent.KEYCODE_MEDIA_PREVIOUS:              case KeyEvent.KEYCODE_MEDIA_REWIND: +            case KeyEvent.KEYCODE_MEDIA_RECORD:              case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:              case KeyEvent.KEYCODE_CAMERA:                  return false; diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 1383354b97f1..4644a7c65a67 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -209,7 +209,12 @@ class LockScreen extends LinearLayout implements KeyguardScreen,                  mSlidingTab.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label                          : R.string.lockscreen_sound_off_label);              } -            mCallback.pokeWakelock(); +            // Don't poke the wake lock when returning to a state where the handle is +            // not grabbed since that can happen when the system (instead of the user) +            // cancels the grab. +            if (grabbedState != SlidingTab.OnTriggerListener.NO_HANDLE) { +                mCallback.pokeWakelock(); +            }          }      } @@ -231,10 +236,11 @@ class LockScreen extends LinearLayout implements KeyguardScreen,          /** {@inheritDoc} */          public void onGrabbedStateChange(View v, int grabbedState) { +            // Don't poke the wake lock when returning to a state where the handle is +            // not grabbed since that can happen when the system (instead of the user) +            // cancels the grab.              if (grabbedState == WaveView.OnTriggerListener.CENTER_HANDLE) {                  mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT); -            } else { -                mCallback.pokeWakelock();              }          }      } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 3691d9716614..e944f9de2059 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -627,13 +627,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {              // should be executed...  do it!              mPanelChordingKey = 0;              mPanelMayLongPress = false; -            InputMethodManager imm = (InputMethodManager) -                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE); -            if (imm != null) { -                mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); -                imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); -            } -                      }          return false; @@ -1259,7 +1252,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {              case KeyEvent.KEYCODE_MEDIA_PLAY:              case KeyEvent.KEYCODE_MEDIA_PAUSE:              case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: -                /* Suppress PLAYPAUSE toggle when phone is ringing or in-call +                /* Suppress PLAY/PAUSE toggle when phone is ringing or in-call                   * to avoid music playback */                  if (mTelephonyManager == null) {                      mTelephonyManager = (TelephonyManager) getContext().getSystemService( @@ -1275,6 +1268,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {              case KeyEvent.KEYCODE_MEDIA_NEXT:              case KeyEvent.KEYCODE_MEDIA_PREVIOUS:              case KeyEvent.KEYCODE_MEDIA_REWIND: +            case KeyEvent.KEYCODE_MEDIA_RECORD:              case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {                  Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);                  intent.putExtra(Intent.EXTRA_KEY_EVENT, event); @@ -1455,6 +1449,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {              }              case KeyEvent.KEYCODE_HEADSETHOOK: +            case KeyEvent.KEYCODE_MUTE:              case KeyEvent.KEYCODE_MEDIA_PLAY:              case KeyEvent.KEYCODE_MEDIA_PAUSE:              case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: @@ -1462,6 +1457,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {              case KeyEvent.KEYCODE_MEDIA_NEXT:              case KeyEvent.KEYCODE_MEDIA_PREVIOUS:              case KeyEvent.KEYCODE_MEDIA_REWIND: +            case KeyEvent.KEYCODE_MEDIA_RECORD:              case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {                  Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);                  intent.putExtra(Intent.EXTRA_KEY_EVENT, event); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 7f49da903909..e950ae5c3241 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -54,6 +54,7 @@ import com.android.internal.telephony.ITelephony;  import com.android.internal.view.BaseInputHandler;  import com.android.internal.widget.PointerLocationView; +import android.telephony.TelephonyManager;  import android.util.Config;  import android.util.EventLog;  import android.util.Log; @@ -63,6 +64,7 @@ import android.view.Gravity;  import android.view.HapticFeedbackConstants;  import android.view.IWindowManager;  import android.view.InputChannel; +import android.view.InputDevice;  import android.view.InputQueue;  import android.view.InputHandler;  import android.view.KeyEvent; @@ -217,7 +219,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {      WindowState mKeyguard = null;      KeyguardViewMediator mKeyguardMediator;      GlobalActions mGlobalActions; -    boolean mShouldTurnOffOnKeyUp; +    volatile boolean mPowerKeyHandled;      RecentApplicationsDialog mRecentAppsDialog;      Handler mHandler; @@ -477,28 +479,47 @@ public class PhoneWindowManager implements WindowManagerPolicy {          }      } -    Runnable mPowerLongPress = new Runnable() { +    private void interceptPowerKeyDown(boolean handled) { +        mPowerKeyHandled = handled; +        if (!handled) { +            mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); +        } +    } + +    private boolean interceptPowerKeyUp(boolean canceled) { +        if (!mPowerKeyHandled) { +            mHandler.removeCallbacks(mPowerLongPress); +            return !canceled; +        } else { +            mPowerKeyHandled = true; +            return false; +        } +    } + +    private final Runnable mPowerLongPress = new Runnable() {          public void run() { -            // The context isn't read -            if (mLongPressOnPowerBehavior < 0) { -                mLongPressOnPowerBehavior = mContext.getResources().getInteger( -                        com.android.internal.R.integer.config_longPressOnPowerBehavior); -            } -            switch (mLongPressOnPowerBehavior) { -            case LONG_PRESS_POWER_NOTHING: -                break; -            case LONG_PRESS_POWER_GLOBAL_ACTIONS: -                mShouldTurnOffOnKeyUp = false; -                performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); -                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); -                showGlobalActionsDialog(); -                break; -            case LONG_PRESS_POWER_SHUT_OFF: -                mShouldTurnOffOnKeyUp = false; -                performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); -                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); -                ShutdownThread.shutdown(mContext, true); -                break; +            if (!mPowerKeyHandled) { +                // The context isn't read +                if (mLongPressOnPowerBehavior < 0) { +                    mLongPressOnPowerBehavior = mContext.getResources().getInteger( +                            com.android.internal.R.integer.config_longPressOnPowerBehavior); +                } +                switch (mLongPressOnPowerBehavior) { +                case LONG_PRESS_POWER_NOTHING: +                    break; +                case LONG_PRESS_POWER_GLOBAL_ACTIONS: +                    mPowerKeyHandled = true; +                    performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); +                    sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); +                    showGlobalActionsDialog(); +                    break; +                case LONG_PRESS_POWER_SHUT_OFF: +                    mPowerKeyHandled = true; +                    performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); +                    sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); +                    ShutdownThread.shutdown(mContext, true); +                    break; +                }              }          }      }; @@ -1111,12 +1132,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {                  com.android.internal.R.anim.lock_screen_behind_enter);      } -    static ITelephony getPhoneInterface() { -        return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE)); +    static ITelephony getTelephonyService() { +        ITelephony telephonyService = ITelephony.Stub.asInterface( +                ServiceManager.checkService(Context.TELEPHONY_SERVICE)); +        if (telephonyService == null) { +            Log.w(TAG, "Unable to find ITelephony interface."); +        } +        return telephonyService;      } -    static IAudioService getAudioInterface() { -        return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE)); +    static IAudioService getAudioService() { +        IAudioService audioService = IAudioService.Stub.asInterface( +                ServiceManager.checkService(Context.AUDIO_SERVICE)); +        if (audioService == null) { +            Log.w(TAG, "Unable to find IAudioService interface."); +        } +        return audioService;      }      boolean keyguardOn() { @@ -1131,7 +1162,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {      /** {@inheritDoc} */      @Override      public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, -            int keyCode, int metaState, int repeatCount, int policyFlags) { +            int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) {          final boolean keyguardOn = keyguardOn();          final boolean down = (action == KeyEvent.ACTION_DOWN);          final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0); @@ -1164,11 +1195,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {                          // and his ONLY options are to answer or reject the call.)                          boolean incomingRinging = false;                          try { -                            ITelephony phoneServ = getPhoneInterface(); -                            if (phoneServ != null) { -                                incomingRinging = phoneServ.isRinging(); -                            } else { -                                Log.w(TAG, "Unable to find ITelephony interface"); +                            ITelephony telephonyService = getTelephonyService(); +                            if (telephonyService != null) { +                                incomingRinging = telephonyService.isRinging();                              }                          } catch (RemoteException ex) {                              Log.w(TAG, "RemoteException from getPhoneInterface()", ex); @@ -1824,23 +1853,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {      }      /** -     * @return Whether a telephone call is in progress right now. -     */ -    boolean isInCall() { -        final ITelephony phone = getPhoneInterface(); -        if (phone == null) { -            Log.w(TAG, "couldn't get ITelephony reference"); -            return false; -        } -        try { -            return phone.isOffhook(); -        } catch (RemoteException e) { -            Log.w(TAG, "ITelephony.isOffhhook threw RemoteException " + e); -            return false; -        } -    } - -    /**       * @return Whether music is being played right now.       */      boolean isMusicActive() { @@ -1857,9 +1869,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {       * @param keycode       */      void handleVolumeKey(int stream, int keycode) { -        final IAudioService audio = getAudioInterface(); -        if (audio == null) { -            Log.w(TAG, "handleVolumeKey: couldn't get IAudioService reference"); +        IAudioService audioService = getAudioService(); +        if (audioService == null) {              return;          }          try { @@ -1867,7 +1878,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {              // during the call, but we do it as a precaution for the rare possibility              // that the music stops right before we call this              mBroadcastWakeLock.acquire(); -            audio.adjustStreamVolume(stream, +            audioService.adjustStreamVolume(stream,                  keycode == KeyEvent.KEYCODE_VOLUME_UP                              ? AudioManager.ADJUST_RAISE                              : AudioManager.ADJUST_LOWER, @@ -1878,41 +1889,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {              mBroadcastWakeLock.release();          }      } -     -    static boolean isMediaKey(int code) { -        if (code == KeyEvent.KEYCODE_HEADSETHOOK ||  -                code == KeyEvent.KEYCODE_MEDIA_PLAY || -                code == KeyEvent.KEYCODE_MEDIA_PAUSE || -                code == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || -                code == KeyEvent.KEYCODE_MEDIA_STOP ||  -                code == KeyEvent.KEYCODE_MEDIA_NEXT || -                code == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||  -                code == KeyEvent.KEYCODE_MEDIA_REWIND || -                code == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) { -            return true; -        } -        return false;     -    } -  +      /** {@inheritDoc} */      @Override -    public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, -            int policyFlags, boolean isScreenOn) { -        int result = ACTION_PASS_TO_USER; +    public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, +            int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { +        final boolean down = action == KeyEvent.ACTION_DOWN; +        final boolean canceled = (flags & KeyEvent.FLAG_CANCELED) != 0; -        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) { -            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); -        } - -        final boolean isWakeKey = (policyFlags -                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; - -        // If the key is injected, pretend that the screen is on and don't let the -        // device go to sleep.  This feature is mainly used for testing purposes.          final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; -        if (isInjected) { -            isScreenOn = true; -        }          // If screen is off then we treat the case where the keyguard is open but hidden          // the same as if it were open and in front. @@ -1927,202 +1912,210 @@ public class PhoneWindowManager implements WindowManagerPolicy {                    + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);          } -        if (keyguardActive) { -            if (isScreenOn) { -                // when the screen is on, always give the event to the keyguard -                result |= ACTION_PASS_TO_USER; -            } else { -                // otherwise, don't pass it to the user -                result &= ~ACTION_PASS_TO_USER; +        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) { +            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); +        } -                if (isWakeKey && down) { - -                    // tell the mediator about a wake key, it may decide to -                    // turn on the screen depending on whether the key is -                    // appropriate. -                    if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode) -                            && (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN -                                || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) { -                        // when keyguard is showing and screen off, we need -                        // to handle the volume key for calls and  music here -                        if (isInCall()) { -                            handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); -                        } else if (isMusicActive()) { -                            handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode); +        // Basic policy based on screen state and keyguard. +        // FIXME: This policy isn't quite correct.  We shouldn't care whether the screen +        //        is on or off, really.  We should care about whether the device is in an +        //        interactive state or is in suspend pretending to be "off". +        //        The primary screen might be turned off due to proximity sensor or +        //        because we are presenting media on an auxiliary screen or remotely controlling +        //        the device some other way (which is why we have an exemption here for injected +        //        events). +        int result; +        if (isScreenOn || isInjected) { +            // When the screen is on or if the key is injected pass the key to the application. +            result = ACTION_PASS_TO_USER; +        } else { +            // When the screen is off and the key is not injected, determine whether +            // to wake the device but don't pass the key to the application. +            result = 0; + +            final boolean isWakeKey = (policyFlags +                    & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; +            if (down && isWakeKey) { +                if (keyguardActive) { +                    // If the keyguard is showing, let it decide what to do with the wake key. +                    mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode); +                } else { +                    // Otherwise, wake the device ourselves. +                    result |= ACTION_POKE_USER_ACTIVITY; +                } +            } +        } + +        // Handle special keys. +        switch (keyCode) { +            case KeyEvent.KEYCODE_VOLUME_DOWN: +            case KeyEvent.KEYCODE_VOLUME_UP: { +                if (down) { +                    ITelephony telephonyService = getTelephonyService(); +                    if (telephonyService != null) { +                        try { +                            if (telephonyService.isRinging()) { +                                // If an incoming call is ringing, either VOLUME key means +                                // "silence ringer".  We handle these keys here, rather than +                                // in the InCallScreen, to make sure we'll respond to them +                                // even if the InCallScreen hasn't come to the foreground yet. +                                // Look for the DOWN event here, to agree with the "fallback" +                                // behavior in the InCallScreen. +                                Log.i(TAG, "interceptKeyBeforeQueueing:" +                                      + " VOLUME key-down while ringing: Silence ringer!"); + +                                // Silence the ringer.  (It's safe to call this +                                // even if the ringer has already been silenced.) +                                telephonyService.silenceRinger(); + +                                // And *don't* pass this key thru to the current activity +                                // (which is probably the InCallScreen.) +                                result &= ~ACTION_PASS_TO_USER; +                                break; +                            } +                            if (telephonyService.isOffhook() +                                    && (result & ACTION_PASS_TO_USER) == 0) { +                                // If we are in call but we decided not to pass the key to +                                // the application, handle the volume change here. +                                handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); +                                break; +                            } +                        } catch (RemoteException ex) { +                            Log.w(TAG, "ITelephony threw RemoteException", ex);                          }                      } + +                    if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) { +                        // If music is playing but we decided not to pass the key to the +                        // application, handle the volume change here. +                        handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode); +                        break; +                    }                  } +                break;              } -        } else if (!isScreenOn) { -            // If we are in-call with screen off and keyguard is not showing, -            // then handle the volume key ourselves. -            // This is necessary because the phone app will disable the keyguard -            // when the proximity sensor is in use. -            if (isInCall() && -                     (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN -                                || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) { -                result &= ~ACTION_PASS_TO_USER; -                handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); -            } -            if (isWakeKey) { -                // a wake key has a sole purpose of waking the device; don't pass -                // it to the user -                result |= ACTION_POKE_USER_ACTIVITY; + +            case KeyEvent.KEYCODE_ENDCALL: {                  result &= ~ACTION_PASS_TO_USER; +                if (down) { +                    ITelephony telephonyService = getTelephonyService(); +                    boolean hungUp = false; +                    if (telephonyService != null) { +                        try { +                            hungUp = telephonyService.endCall(); +                        } catch (RemoteException ex) { +                            Log.w(TAG, "ITelephony threw RemoteException", ex); +                        } +                    } +                    interceptPowerKeyDown(!isScreenOn || hungUp); +                } else { +                    if (interceptPowerKeyUp(canceled)) { +                        if ((mEndcallBehavior +                                & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { +                            if (goHome()) { +                                break; +                            } +                        } +                        if ((mEndcallBehavior +                                & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { +                            result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP; +                        } +                    } +                } +                break;              } -        } -        if (keyCode == KeyEvent.KEYCODE_ENDCALL -                || keyCode == KeyEvent.KEYCODE_POWER) { -            if (down) { -                boolean handled = false; -                boolean hungUp = false; -                // key repeats are generated by the window manager, and we don't see them -                // here, so unless the driver is doing something it shouldn't be, we know -                // this is the real press event. -                ITelephony phoneServ = getPhoneInterface(); -                if (phoneServ != null) { -                    try { -                        if (keyCode == KeyEvent.KEYCODE_ENDCALL) { -                            handled = hungUp = phoneServ.endCall(); -                        } else if (keyCode == KeyEvent.KEYCODE_POWER) { -                            if (phoneServ.isRinging()) { +            case KeyEvent.KEYCODE_POWER: { +                result &= ~ACTION_PASS_TO_USER; +                if (down) { +                    ITelephony telephonyService = getTelephonyService(); +                    boolean hungUp = false; +                    if (telephonyService != null) { +                        try { +                            if (telephonyService.isRinging()) {                                  // Pressing Power while there's a ringing incoming                                  // call should silence the ringer. -                                phoneServ.silenceRinger(); -                                handled = true; -                            } else if (phoneServ.isOffhook() && -                                       ((mIncallPowerBehavior -                                         & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) -                                        != 0)) { +                                telephonyService.silenceRinger(); +                            } else if ((mIncallPowerBehavior +                                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 +                                    && telephonyService.isOffhook()) {                                  // Otherwise, if "Power button ends call" is enabled,                                  // the Power button will hang up any current active call. -                                handled = hungUp = phoneServ.endCall(); +                                hungUp = telephonyService.endCall();                              } +                        } catch (RemoteException ex) { +                            Log.w(TAG, "ITelephony threw RemoteException", ex);                          } -                    } catch (RemoteException ex) { -                        Log.w(TAG, "ITelephony threw RemoteException" + ex);                      } +                    interceptPowerKeyDown(!isScreenOn || hungUp);                  } else { -                    Log.w(TAG, "!!! Unable to find ITelephony interface !!!"); -                } - -                if (!isScreenOn -                        || (handled && keyCode != KeyEvent.KEYCODE_POWER) -                        || (handled && hungUp && keyCode == KeyEvent.KEYCODE_POWER)) { -                    mShouldTurnOffOnKeyUp = false; -                } else { -                    // Only try to turn off the screen if we didn't already hang up. -                    mShouldTurnOffOnKeyUp = true; -                    mHandler.postDelayed(mPowerLongPress, -                            ViewConfiguration.getGlobalActionKeyTimeout()); -                    result &= ~ACTION_PASS_TO_USER; -                } -            } else { -                mHandler.removeCallbacks(mPowerLongPress); -                if (mShouldTurnOffOnKeyUp) { -                    mShouldTurnOffOnKeyUp = false; -                    boolean gohome, sleeps; -                    if (keyCode == KeyEvent.KEYCODE_ENDCALL) { -                        gohome = (mEndcallBehavior -                                  & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0; -                        sleeps = (mEndcallBehavior -                                  & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0; -                    } else { -                        gohome = false; -                        sleeps = true; -                    } -                    if (keyguardActive -                            || (sleeps && !gohome) -                            || (gohome && !goHome() && sleeps)) { -                        // They must already be on the keyguard or home screen, -                        // go to sleep instead unless the event was injected. -                        if (!isInjected) { -                            Log.d(TAG, "I'm tired mEndcallBehavior=0x" -                                    + Integer.toHexString(mEndcallBehavior)); -                            result &= ~ACTION_POKE_USER_ACTIVITY; -                            result |= ACTION_GO_TO_SLEEP; -                        } +                    if (interceptPowerKeyUp(canceled)) { +                        result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;                      } -                    result &= ~ACTION_PASS_TO_USER;                  } +                break;              } -        } else if (isMediaKey(keyCode)) { -            // This key needs to be handled even if the screen is off. -            // If others need to be handled while it's off, this is a reasonable -            // pattern to follow. -            if ((result & ACTION_PASS_TO_USER) == 0) { -                // Only do this if we would otherwise not pass it to the user. In that -                // case, the PhoneWindow class will do the same thing, except it will -                // only do it if the showing app doesn't process the key on its own. -                long when = whenNanos / 1000000; -                KeyEvent keyEvent = new KeyEvent(when, when, -                        down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP, -                        keyCode, 0); -                mBroadcastWakeLock.acquire(); -                mHandler.post(new PassHeadsetKey(keyEvent)); -            } -        } else if (keyCode == KeyEvent.KEYCODE_CALL) { -            // If an incoming call is ringing, answer it! -            // (We handle this key here, rather than in the InCallScreen, to make -            // sure we'll respond to the key even if the InCallScreen hasn't come to -            // the foreground yet.) - -            // We answer the call on the DOWN event, to agree with -            // the "fallback" behavior in the InCallScreen. -            if (down) { -                try { -                    ITelephony phoneServ = getPhoneInterface(); -                    if (phoneServ != null) { -                        if (phoneServ.isRinging()) { -                            Log.i(TAG, "interceptKeyTq:" -                                  + " CALL key-down while ringing: Answer the call!"); -                            phoneServ.answerRingingCall(); - -                            // And *don't* pass this key thru to the current activity -                            // (which is presumably the InCallScreen.) -                            result &= ~ACTION_PASS_TO_USER; + +            case KeyEvent.KEYCODE_MEDIA_PLAY: +            case KeyEvent.KEYCODE_MEDIA_PAUSE: +            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: +                if (down) { +                    ITelephony telephonyService = getTelephonyService(); +                    if (telephonyService != null) { +                        try { +                            if (!telephonyService.isIdle()) { +                                // Suppress PLAY/PAUSE toggle when phone is ringing or in-call +                                // to avoid music playback. +                                break; +                            } +                        } catch (RemoteException ex) { +                            Log.w(TAG, "ITelephony threw RemoteException", ex);                          } -                    } else { -                        Log.w(TAG, "CALL button: Unable to find ITelephony interface");                      } -                } catch (RemoteException ex) { -                    Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex);                  } +            case KeyEvent.KEYCODE_HEADSETHOOK: +            case KeyEvent.KEYCODE_MUTE: +            case KeyEvent.KEYCODE_MEDIA_STOP: +            case KeyEvent.KEYCODE_MEDIA_NEXT: +            case KeyEvent.KEYCODE_MEDIA_PREVIOUS: +            case KeyEvent.KEYCODE_MEDIA_REWIND: +            case KeyEvent.KEYCODE_MEDIA_RECORD: +            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { +                if ((result & ACTION_PASS_TO_USER) == 0) { +                    // Only do this if we would otherwise not pass it to the user. In that +                    // case, the PhoneWindow class will do the same thing, except it will +                    // only do it if the showing app doesn't process the key on its own. +                    long when = whenNanos / 1000000; +                    KeyEvent keyEvent = new KeyEvent(when, when, action, keyCode, 0, 0, +                            0, scanCode, flags, InputDevice.SOURCE_KEYBOARD); +                    mBroadcastWakeLock.acquire(); +                    mHandler.post(new PassHeadsetKey(keyEvent)); +                } +                break;              } -        } else if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) -                   || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) { -            // If an incoming call is ringing, either VOLUME key means -            // "silence ringer".  We handle these keys here, rather than -            // in the InCallScreen, to make sure we'll respond to them -            // even if the InCallScreen hasn't come to the foreground yet. - -            // Look for the DOWN event here, to agree with the "fallback" -            // behavior in the InCallScreen. -            if (down) { -                try { -                    ITelephony phoneServ = getPhoneInterface(); -                    if (phoneServ != null) { -                        if (phoneServ.isRinging()) { -                            Log.i(TAG, "interceptKeyTq:" -                                  + " VOLUME key-down while ringing: Silence ringer!"); -                            // Silence the ringer.  (It's safe to call this -                            // even if the ringer has already been silenced.) -                            phoneServ.silenceRinger(); - -                            // And *don't* pass this key thru to the current activity -                            // (which is probably the InCallScreen.) -                            result &= ~ACTION_PASS_TO_USER; + +            case KeyEvent.KEYCODE_CALL: { +                if (down) { +                    ITelephony telephonyService = getTelephonyService(); +                    if (telephonyService != null) { +                        try { +                            if (telephonyService.isRinging()) { +                                Log.i(TAG, "interceptKeyBeforeQueueing:" +                                      + " CALL key-down while ringing: Answer the call!"); +                                telephonyService.answerRingingCall(); + +                                // And *don't* pass this key thru to the current activity +                                // (which is presumably the InCallScreen.) +                                result &= ~ACTION_PASS_TO_USER; +                            } +                        } catch (RemoteException ex) { +                            Log.w(TAG, "ITelephony threw RemoteException", ex);                          } -                    } else { -                        Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");                      } -                } catch (RemoteException ex) { -                    Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);                  } +                break;              }          } -          return result;      } diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index cb4071a2a9bf..e7eb1293d0e0 100644 --- a/services/java/com/android/server/InputManager.java +++ b/services/java/com/android/server/InputManager.java @@ -404,17 +404,18 @@ public class InputManager {          }          @SuppressWarnings("unused") -        public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, -                int policyFlags, boolean isScreenOn) { +        public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, +                int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {              return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing( -                    whenNanos, keyCode, down, policyFlags, isScreenOn); +                    whenNanos, action, flags, keyCode, scanCode, policyFlags, isScreenOn);          }          @SuppressWarnings("unused")          public boolean interceptKeyBeforeDispatching(InputChannel focus, int action, -                int flags, int keyCode, int metaState, int repeatCount, int policyFlags) { +                int flags, int keyCode, int scanCode, int metaState, int repeatCount, +                int policyFlags) {              return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus, -                    action, flags, keyCode, metaState, repeatCount, policyFlags); +                    action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags);          }          @SuppressWarnings("unused") diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index 747af265e321..a7a0c682d93a 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -103,6 +103,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {      private int mDataConnectionNetworkType; +    private int mOtaspMode; +      static final int PHONE_STATE_PERMISSION_MASK =                  PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |                  PhoneStateListener.LISTEN_CALL_STATE | @@ -225,6 +227,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {                              remove(r.binder);                          }                      } +                    if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { +                        try { +                            r.callback.onOtaspChanged(mOtaspMode); +                        } catch (RemoteException ex) { +                            remove(r.binder); +                        } +                    }                  }              }          } else { @@ -467,6 +476,25 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {          }      } +    public void notifyOtaspChanged(int otaspMode) { +        if (!checkNotifyPermission("notifyOtaspChanged()" )) { +            return; +        } +        synchronized (mRecords) { +            mOtaspMode = otaspMode; +            for (Record r : mRecords) { +                if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { +                    try { +                        r.callback.onOtaspChanged(otaspMode); +                    } catch (RemoteException ex) { +                        mRemoveList.add(r.binder); +                    } +                } +            } +            handleRemoveListLocked(); +        } +    } +      @Override      public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {          if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index c29e4a912323..55ebdedb3443 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5706,20 +5706,20 @@ public class WindowManagerService extends IWindowManager.Stub          /* Provides an opportunity for the window manager policy to intercept early key           * processing as soon as the key has been read from the device. */ -        public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, -                int policyFlags, boolean isScreenOn) { -            return mPolicy.interceptKeyBeforeQueueing(whenNanos, -                    keyCode, down, policyFlags, isScreenOn); +        public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags, +                int keyCode, int scanCode, int policyFlags, boolean isScreenOn) { +            return mPolicy.interceptKeyBeforeQueueing(whenNanos, action, flags, +                    keyCode, scanCode, policyFlags, isScreenOn);          }          /* Provides an opportunity for the window manager policy to process a key before           * ordinary dispatch. */          public boolean interceptKeyBeforeDispatching(InputChannel focus, -                int action, int flags, int keyCode, int metaState, int repeatCount, +                int action, int flags, int keyCode, int scanCode, int metaState, int repeatCount,                  int policyFlags) {              WindowState windowState = getWindowStateForInputChannel(focus);              return mPolicy.interceptKeyBeforeDispatching(windowState, action, flags, -                    keyCode, metaState, repeatCount, policyFlags); +                    keyCode, scanCode, metaState, repeatCount, policyFlags);          }          /* Called when the current input focus changes. diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 599163b27b87..d4c4ba4c5a73 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -857,7 +857,7 @@ void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when,          JNIEnv* env = jniEnv();          jint wmActions = env->CallIntMethod(mCallbacksObj,                  gCallbacksClassInfo.interceptKeyBeforeQueueing, -                when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn); +                when, action, flags, keyCode, scanCode, policyFlags, isScreenOn);          if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {              wmActions = 0;          } @@ -926,7 +926,7 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& i          jboolean consumed = env->CallBooleanMethod(mCallbacksObj,                  gCallbacksClassInfo.interceptKeyBeforeDispatching,                  inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), -                keyEvent->getKeyCode(), keyEvent->getMetaState(), +                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),                  keyEvent->getRepeatCount(), policyFlags);          bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); @@ -1358,10 +1358,10 @@ int register_android_server_InputManager(JNIEnv* env) {              "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");      GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz, -            "interceptKeyBeforeQueueing", "(JIZIZ)I"); +            "interceptKeyBeforeQueueing", "(JIIIIIZ)I");      GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz, -            "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z"); +            "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIIII)Z");      GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,              "checkInjectEventsPermission", "(II)Z"); diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index 38f44d863bd4..eda9b71b6722 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -148,6 +148,14 @@ public class PhoneStateListener {       */      public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100; +    /** +     * Listen for changes to OTASP mode. +     * +     * @see #onOtaspChanged +     * @hide +     */ +    public static final int LISTEN_OTASP_CHANGED                            = 0x00000200; +      public PhoneStateListener() {      } @@ -252,6 +260,21 @@ public class PhoneStateListener {          // default implementation empty      } + +    /** +     * The Over The Air Service Provisioning (OTASP) has changed. Requires +     * the READ_PHONE_STATE permission. +     * @param otaspMode is integer <code>OTASP_UNKNOWN=1<code> +     *   means the value is currently unknown and the system should wait until +     *   <code>OTASP_NEEDED=2<code> or <code>OTASP_NOT_NEEDED=3<code> is received before +     *   making the decisision to perform OTASP or not. +     * +     * @hide +     */ +    public void onOtaspChanged(int otaspMode) { +        // default implementation empty +    } +      /**       * The callback methods need to be called on the handler thread where       * this object was created.  If the binder did that for us it'd be nice. @@ -292,9 +315,14 @@ public class PhoneStateListener {          public void onDataActivity(int direction) {              Message.obtain(mHandler, LISTEN_DATA_ACTIVITY, direction, 0, null).sendToTarget();          } +          public void onSignalStrengthsChanged(SignalStrength signalStrength) {              Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength).sendToTarget();          } + +        public void onOtaspChanged(int otaspMode) { +            Message.obtain(mHandler, LISTEN_OTASP_CHANGED, otaspMode, 0).sendToTarget(); +        }      };      Handler mHandler = new Handler() { @@ -329,6 +357,9 @@ public class PhoneStateListener {                  case LISTEN_SIGNAL_STRENGTHS:                      PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);                      break; +                case LISTEN_OTASP_CHANGED: +                    PhoneStateListener.this.onOtaspChanged(msg.arg1); +                    break;              }          }      }; diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java index 6a163ddd2b99..14808b6e37aa 100644 --- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java +++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java @@ -148,6 +148,14 @@ public class DefaultPhoneNotifier implements PhoneNotifier {          }      } +    public void notifyOtaspChanged(Phone sender, int otaspMode) { +        try { +            mRegistry.notifyOtaspChanged(otaspMode); +        } catch (RemoteException ex) { +            // system process is dead +        } +    } +      private void log(String s) {          Log.d(LOG_TAG, "[PhoneNotifier] " + s);      } diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl index 856d6638d71b..082c09728af0 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -32,5 +32,6 @@ oneway interface IPhoneStateListener {      void onDataConnectionStateChanged(int state, int networkType);      void onDataActivity(int direction);      void onSignalStrengthsChanged(in SignalStrength signalStrength); +    void onOtaspChanged(in int otaspMode);  } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 7a1587bd184c..3c4bb12ff7bc 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -66,7 +66,7 @@ interface ITelephony {      boolean showCallScreenWithDialpad(boolean showDialpad);      /** -     * End call or go to the Home screen +     * End call if there is a call in progress, otherwise does nothing.       *       * @return whether it hung up       */ diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 6407a4ebcf80..3c83e50c4f3a 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -38,4 +38,5 @@ interface ITelephonyRegistry {              in LinkCapabilities linkCapabilities, int networkType);      void notifyDataConnectionFailed(String reason, String apnType);      void notifyCellLocation(in Bundle cellLocation); +    void notifyOtaspChanged(in int otaspMode);  } diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index 74e8c1b5624e..554a7bacf582 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -750,6 +750,10 @@ public abstract class PhoneBase extends Handler implements Phone {          mNotifier.notifyDataConnection(this, reason, apnType);      } +    public void notifyOtaspChanged(int otaspMode) { +        mNotifier.notifyOtaspChanged(this, otaspMode); +    } +      public abstract String getPhoneName();      public abstract int getPhoneType(); diff --git a/telephony/java/com/android/internal/telephony/PhoneNotifier.java b/telephony/java/com/android/internal/telephony/PhoneNotifier.java index 691271fc772c..b1cf953e5067 100644 --- a/telephony/java/com/android/internal/telephony/PhoneNotifier.java +++ b/telephony/java/com/android/internal/telephony/PhoneNotifier.java @@ -42,4 +42,5 @@ public interface PhoneNotifier {      public void notifyDataActivity(Phone sender); +    public void notifyOtaspChanged(Phone sender, int otaspMode);  } diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java index e8bbe5e9ecac..3f9ffc3d244c 100644 --- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java @@ -53,6 +53,12 @@ public abstract class ServiceStateTracker extends Handler {      public SignalStrength mSignalStrength; +    /* The otaspMode passed to PhoneStateListener#onOtaspChanged */ +    static public final int OTASP_UNINITIALIZED = 0; +    static public final int OTASP_UNKNOWN = 1; +    static public final int OTASP_NEEDED = 2; +    static public final int OTASP_NOT_NEEDED = 3; +      /**       * A unique identifier to track requests associated with a poll       * and ignore stale responses.  The value is a count-down of @@ -268,9 +274,11 @@ public abstract class ServiceStateTracker extends Handler {      public abstract void handleMessage(Message msg); +    protected abstract Phone getPhone();      protected abstract void handlePollStateResult(int what, AsyncResult ar);      protected abstract void updateSpnDisplay();      protected abstract void setPowerStateToDesired(); +    protected abstract void log(String s);      /**       * Clean up existing voice and data connection then turn off radio power. diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 6e53ec5b458f..b9d5673246d4 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -61,6 +61,7 @@ import com.android.internal.telephony.PhoneBase;  import com.android.internal.telephony.PhoneNotifier;  import com.android.internal.telephony.PhoneProxy;  import com.android.internal.telephony.PhoneSubInfo; +import com.android.internal.telephony.ServiceStateTracker;  import com.android.internal.telephony.TelephonyIntents;  import com.android.internal.telephony.TelephonyProperties;  import com.android.internal.telephony.UUSInfo; @@ -83,10 +84,6 @@ public class CDMAPhone extends PhoneBase {      static final String LOG_TAG = "CDMA";      private static final boolean DBG = true; -    // Min values used to by needsActivation -    private static final String UNACTIVATED_MIN2_VALUE = "000000"; -    private static final String UNACTIVATED_MIN_VALUE = "1111110111"; -      // Default Emergency Callback Mode exit timer      private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000; @@ -1170,19 +1167,7 @@ public class CDMAPhone extends PhoneBase {       */      @Override      public boolean needsOtaServiceProvisioning() { -        String cdmaMin = getCdmaMin(); -        boolean needsProvisioning; -        if (cdmaMin == null || (cdmaMin.length() < 6)) { -            if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: illegal cdmaMin='" -                                    + cdmaMin + "' assume provisioning needed."); -            needsProvisioning = true; -        } else { -            needsProvisioning = (cdmaMin.equals(UNACTIVATED_MIN_VALUE) -                    || cdmaMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE)) -                    || SystemProperties.getBoolean("test_cdma_setup", false); -        } -        if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: ret=" + needsProvisioning); -        return needsProvisioning; +        return mSST.getOtasp() != ServiceStateTracker.OTASP_NOT_NEEDED;      }      private static final String IS683A_FEATURE_CODE = "*228"; diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java index 3669e6062b02..325c2e13a74e 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java @@ -354,6 +354,24 @@ public final class CdmaCallTracker extends CallTracker {                      || (foregroundCall.getState() == CdmaCall.State.ACTIVE)                      || !backgroundCall.getState().isAlive()); +        if (!ret) { +            log(String.format("canDial is false\n" + +                              "((serviceState=%d) != ServiceState.STATE_POWER_OFF)::=%s\n" + +                              "&& pendingMO == null::=%s\n" + +                              "&& !ringingCall.isRinging()::=%s\n" + +                              "&& !disableCall.equals(\"true\")::=%s\n" + +                              "&& (!foregroundCall.getState().isAlive()::=%s\n" + +                              "   || foregroundCall.getState() == CdmaCall.State.ACTIVE::=%s\n" + +                              "   ||!backgroundCall.getState().isAlive())::=%s)", +                    serviceState, +                    serviceState != ServiceState.STATE_POWER_OFF, +                    pendingMO == null, +                    !ringingCall.isRinging(), +                    !disableCall.equals("true"), +                    !foregroundCall.getState().isAlive(), +                    foregroundCall.getState() == CdmaCall.State.ACTIVE, +                    !backgroundCall.getState().isAlive())); +        }          return ret;      } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 7d2013bd4e1c..11e04d4d2525 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -22,6 +22,7 @@ import com.android.internal.telephony.DataConnectionTracker;  import com.android.internal.telephony.EventLogTags;  import com.android.internal.telephony.IccCard;  import com.android.internal.telephony.MccTable; +import com.android.internal.telephony.Phone;  import com.android.internal.telephony.ServiceStateTracker;  import com.android.internal.telephony.TelephonyIntents;  import com.android.internal.telephony.TelephonyProperties; @@ -65,6 +66,13 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {      CdmaCellLocation cellLoc;      CdmaCellLocation newCellLoc; +    // Min values used to by getOtasp() +    private static final String UNACTIVATED_MIN2_VALUE = "000000"; +    private static final String UNACTIVATED_MIN_VALUE = "1111110111"; + +    // Current Otasp value +    int mCurrentOtaspMode = OTASP_UNINITIALIZED; +       /** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */      private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10;      private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing", @@ -446,6 +454,13 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {                      if (!mIsMinInfoReady) {                          mIsMinInfoReady = true;                      } +                    int otaspMode = getOtasp(); +                    if (mCurrentOtaspMode != otaspMode) { +                        Log.d(LOG_TAG, "call phone.notifyOtaspChanged old otaspMode=" + +                                mCurrentOtaspMode + " new otaspMode=" + otaspMode); +                        mCurrentOtaspMode = otaspMode; +                        phone.notifyOtaspChanged(mCurrentOtaspMode); +                    }                      phone.getIccCard().broadcastIccStateChangedIntent(IccCard.INTENT_VALUE_ICC_IMSI,                              null);                  } else { @@ -642,6 +657,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {          curPlmn = plmn;      } +    @Override +    protected Phone getPhone() { +        return phone; +    } +      /**       * Handle the result of one of the pollState()-related requests       */ @@ -1641,10 +1661,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {          return false;      } -    protected void log(String s) { -        Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s); -    } -      public String getMdnNumber() {          return mMdn;      } @@ -1700,6 +1716,32 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {          }      } +    /** +     * Returns OTASP_UNKNOWN, OTASP_NEEDED or OTASP_NOT_NEEDED +     */ +    int getOtasp() { +        int provisioningState; +        if (mMin == null || (mMin.length() < 6)) { +            if (DBG) Log.d(LOG_TAG, "getOtasp: bad mMin='" + mMin + "'"); +            provisioningState = OTASP_UNKNOWN; +        } else { +            if ((mMin.equals(UNACTIVATED_MIN_VALUE) +                    || mMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE)) +                    || SystemProperties.getBoolean("test_cdma_setup", false)) { +                provisioningState = OTASP_NEEDED; +            } else { +                provisioningState = OTASP_NOT_NEEDED; +            } +        } +        if (DBG) Log.d(LOG_TAG, "getOtasp: state=" + provisioningState); +        return provisioningState; +    } + +    @Override +    protected void log(String s) { +        Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s); +    } +      private void hangupAndPowerOff() {          // hang up all active voice calls          phone.mCT.ringingCall.hangupIfAlive(); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 633241573bd8..bc41b01bdc77 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -22,6 +22,7 @@ import com.android.internal.telephony.DataConnectionTracker;  import com.android.internal.telephony.EventLogTags;  import com.android.internal.telephony.IccCard;  import com.android.internal.telephony.MccTable; +import com.android.internal.telephony.Phone;  import com.android.internal.telephony.RILConstants;  import com.android.internal.telephony.ServiceStateTracker;  import com.android.internal.telephony.TelephonyIntents; @@ -226,6 +227,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {          IntentFilter filter = new IntentFilter();          filter.addAction(Intent.ACTION_LOCALE_CHANGED);          phone.getContext().registerReceiver(mIntentReceiver, filter); + +        // Gsm doesn't support OTASP so its not needed +        phone.notifyOtaspChanged(OTASP_NOT_NEEDED);      }      public void dispose() { @@ -246,6 +250,11 @@ final class GsmServiceStateTracker extends ServiceStateTracker {          if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized");      } +    @Override +    public Phone getPhone() { +        return phone; +    } +      /**       * Registration point for transition into GPRS attached.       * @param h handler to notify @@ -1676,7 +1685,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker {          }      } -    private void log(String s) { +    @Override +    protected void log(String s) {          Log.d(LOG_TAG, "[GsmServiceStateTracker] " + s);      }  } diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java index 8cb05cc19209..7bbe696e7a7a 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java @@ -56,4 +56,7 @@ public class TestPhoneNotifier implements PhoneNotifier {      public void notifyDataActivity(Phone sender) {      } + +    public void notifyOtaspChanged(Phone sender, int otaspMode) { +    }  } diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 24fba72a2026..e97b1e63730c 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -60,6 +60,20 @@ public class Bitmap_Delegate {      // ---- Public Helper methods ----      /** +     * Returns the native delegate associated to a given {@link Bitmap_Delegate} object. +     */ +    public static Bitmap_Delegate getDelegate(Bitmap bitmap) { +        return sManager.getDelegate(bitmap.mNativeBitmap); +    } + +    /** +     * Returns the native delegate associated to a given an int referencing a {@link Bitmap} object. +     */ +    public static Bitmap_Delegate getDelegate(int native_bitmap) { +        return sManager.getDelegate(native_bitmap); +    } + +    /**       * Creates and returns a {@link Bitmap} initialized with the given file content.       */      public static Bitmap createBitmap(File input, Density density) throws IOException { @@ -118,6 +132,13 @@ public class Bitmap_Delegate {          return BufferedImage.TYPE_INT_ARGB;      } +    /** +     * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}. +     */ +    public BufferedImage getImage() { +        return mImage; +    } +      // ---- native methods ----      /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width, @@ -127,8 +148,7 @@ public class Bitmap_Delegate {          // create the image          BufferedImage image = new BufferedImage(width, height, imageType); -        // fill it -        //image.setRGB(x, y, rgb) +        // FIXME fill the bitmap!          // create a delegate with the content of the stream.          Bitmap_Delegate delegate = new Bitmap_Delegate(image); diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java deleted file mode 100644 index 24da812eaa31..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas.java +++ /dev/null @@ -1,1247 +0,0 @@ -/* - * Copyright (C) 2008 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 android.graphics; - -import com.android.layoutlib.api.ILayoutLog; - -import android.graphics.Paint.Align; -import android.graphics.Paint.FontInfo; -import android.graphics.Paint.Style; -import android.graphics.Region.Op; - -import java.awt.AlphaComposite; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.util.List; -import java.util.Stack; - -/** - * Re-implementation of the Canvas, 100% in java on top of a BufferedImage. - */ -public class Canvas extends _Original_Canvas { - -    private BufferedImage mBufferedImage; -    private final Stack<Graphics2D> mGraphicsStack = new Stack<Graphics2D>(); -    private final ILayoutLog mLogger; - -    public Canvas() { -        mLogger = null; -        // the mBufferedImage will be taken from a bitmap in #setBitmap() -    } - -    public Canvas(Bitmap bitmap) { -        mLogger = null; -        mBufferedImage = Bitmap_Delegate.getImage(bitmap); -        mGraphicsStack.push(mBufferedImage.createGraphics()); -    } - -    public Canvas(int nativeCanvas) { -        mLogger = null; -        throw new UnsupportedOperationException("Can't create Canvas(int)"); -    } - -    // custom constructors for our use. -    public Canvas(int width, int height, ILayoutLog logger) { -        mLogger = logger; -        mBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); -        mGraphicsStack.push(mBufferedImage.createGraphics()); -    } - -    public Canvas(int width, int height) { -        this(width, height, null /* logger*/); -    } - -    // custom mehtods -    public BufferedImage getImage() { -        return mBufferedImage; -    } - -    public Graphics2D getGraphics2d() { -        return mGraphicsStack.peek(); -    } - -    public void dispose() { -        while (mGraphicsStack.size() > 0) { -            mGraphicsStack.pop().dispose(); -        } -    } - -    /** -     * Creates a new {@link Graphics2D} based on the {@link Paint} parameters. -     * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. -     */ -    private Graphics2D getCustomGraphics(Paint paint) { -        // make new one -        Graphics2D g = getGraphics2d(); -        g = (Graphics2D)g.create(); - -        // configure it -        g.setColor(new Color(paint.getColor())); -        int alpha = paint.getAlpha(); -        float falpha = alpha / 255.f; - -        Style style = paint.getStyle(); -        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { -            PathEffect e = paint.getPathEffect(); -            if (e instanceof DashPathEffect) { -                DashPathEffect dpe = (DashPathEffect)e; -                g.setStroke(new BasicStroke( -                        paint.getStrokeWidth(), -                        paint.getStrokeCap().getJavaCap(), -                        paint.getStrokeJoin().getJavaJoin(), -                        paint.getStrokeMiter(), -                        dpe.getIntervals(), -                        dpe.getPhase())); -            } else { -                g.setStroke(new BasicStroke( -                        paint.getStrokeWidth(), -                        paint.getStrokeCap().getJavaCap(), -                        paint.getStrokeJoin().getJavaJoin(), -                        paint.getStrokeMiter())); -            } -        } - -        Xfermode xfermode = paint.getXfermode(); -        if (xfermode instanceof PorterDuffXfermode) { -            PorterDuff.Mode mode = ((PorterDuffXfermode)xfermode).getMode(); - -            setModeInGraphics(mode, g, falpha); -        } else { -            if (mLogger != null && xfermode != null) { -                mLogger.warning(String.format( -                        "Xfermode '%1$s' is not supported in the Layout Editor.", -                        xfermode.getClass().getCanonicalName())); -            } -            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); -        } - -        Shader shader = paint.getShader(); -        if (shader != null) { -            java.awt.Paint shaderPaint = shader.getJavaPaint(); -            if (shaderPaint != null) { -                g.setPaint(shaderPaint); -            } else { -                if (mLogger != null) { -                    mLogger.warning(String.format( -                            "Shader '%1$s' is not supported in the Layout Editor.", -                            shader.getClass().getCanonicalName())); -                } -            } -        } - -        return g; -    } - -    private void setModeInGraphics(PorterDuff.Mode mode, Graphics2D g, float falpha) { -        switch (mode) { -            case CLEAR: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha)); -                break; -            case DARKEN: -                break; -            case DST: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, falpha)); -                break; -            case DST_ATOP: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha)); -                break; -            case DST_IN: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha)); -                break; -            case DST_OUT: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha)); -                break; -            case DST_OVER: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha)); -                break; -            case LIGHTEN: -                break; -            case MULTIPLY: -                break; -            case SCREEN: -                break; -            case SRC: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, falpha)); -                break; -            case SRC_ATOP: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha)); -                break; -            case SRC_IN: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha)); -                break; -            case SRC_OUT: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha)); -                break; -            case SRC_OVER: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); -                break; -            case XOR: -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, falpha)); -                break; -        } -    } - - -    // -------------------- -    // OVERRIDEN ENUMS -    // This is needed since we rename Canvas into _Original_Canvas -    // -------------------- - -    public enum EdgeType { -        BW(0),  //!< treat edges by just rounding to nearest pixel boundary -        AA(1);  //!< treat edges by rounding-out, since they may be antialiased - -        EdgeType(int nativeInt) { -            this.nativeInt = nativeInt; -        } -        final int nativeInt; -    } - - -    // -------------------- -    // OVERRIDEN METHODS -    // -------------------- - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#setBitmap(android.graphics.Bitmap) -     */ -    @Override -    public void setBitmap(Bitmap bitmap) { -        mBufferedImage = Bitmap_Delegate.getImage(bitmap); -        mGraphicsStack.push(mBufferedImage.createGraphics()); -    } - - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#translate(float, float) -     */ -    @Override -    public void translate(float dx, float dy) { -        getGraphics2d().translate(dx, dy); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#save() -     */ -    @Override -    public int save() { -        // get the current save count -        int count = mGraphicsStack.size(); - -        // create a new graphics and add it to the stack -        Graphics2D g = (Graphics2D)getGraphics2d().create(); -        mGraphicsStack.push(g); - -        // return the old save count -        return count; -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#save(int) -     */ -    @Override -    public int save(int saveFlags) { -        // For now we ignore saveFlags -        return save(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#restore() -     */ -    @Override -    public void restore() { -        mGraphicsStack.pop(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#restoreToCount(int) -     */ -    @Override -    public void restoreToCount(int saveCount) { -        while (mGraphicsStack.size() > saveCount) { -            mGraphicsStack.pop(); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#getSaveCount() -     */ -    @Override -    public int getSaveCount() { -        return mGraphicsStack.size(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRect(float, float, float, float, android.graphics.Region.Op) -     */ -    @Override -    public boolean clipRect(float left, float top, float right, float bottom, Op op) { -        return clipRect(left, top, right, bottom); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRect(float, float, float, float) -     */ -    @Override -    public boolean clipRect(float left, float top, float right, float bottom) { -        getGraphics2d().clipRect((int)left, (int)top, (int)(right-left), (int)(bottom-top)); -        return true; -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRect(int, int, int, int) -     */ -    @Override -    public boolean clipRect(int left, int top, int right, int bottom) { -        getGraphics2d().clipRect(left, top, right-left, bottom-top); -        return true; -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRect(android.graphics.Rect, android.graphics.Region.Op) -     */ -    @Override -    public boolean clipRect(Rect rect, Op op) { -        return clipRect(rect.left, rect.top, rect.right, rect.bottom); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRect(android.graphics.Rect) -     */ -    @Override -    public boolean clipRect(Rect rect) { -        return clipRect(rect.left, rect.top, rect.right, rect.bottom); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRect(android.graphics.RectF, android.graphics.Region.Op) -     */ -    @Override -    public boolean clipRect(RectF rect, Op op) { -        return clipRect(rect.left, rect.top, rect.right, rect.bottom); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRect(android.graphics.RectF) -     */ -    @Override -    public boolean clipRect(RectF rect) { -        return clipRect(rect.left, rect.top, rect.right, rect.bottom); -    } - -    public boolean quickReject(RectF rect, EdgeType type) { -        return false; -    } - -    @Override -    public boolean quickReject(RectF rect, _Original_Canvas.EdgeType type) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    public boolean quickReject(Path path, EdgeType type) { -        return false; -    } - -    @Override -    public boolean quickReject(Path path, _Original_Canvas.EdgeType type) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    public boolean quickReject(float left, float top, float right, float bottom, -                               EdgeType type) { -        return false; -    } - -    @Override -    public boolean quickReject(float left, float top, float right, float bottom, -                               _Original_Canvas.EdgeType type) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    /** -     * Retrieve the clip bounds, returning true if they are non-empty. -     * -     * @param bounds Return the clip bounds here. If it is null, ignore it but -     *               still return true if the current clip is non-empty. -     * @return true if the current clip is non-empty. -     */ -    @Override -    public boolean getClipBounds(Rect bounds) { -        Rectangle rect = getGraphics2d().getClipBounds(); -        if (rect != null) { -            bounds.left = rect.x; -            bounds.top = rect.y; -            bounds.right = rect.x + rect.width; -            bounds.bottom = rect.y + rect.height; -            return true; -        } -        return false; -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawColor(int, android.graphics.PorterDuff.Mode) -     */ -    @Override -    public void drawColor(int color, PorterDuff.Mode mode) { -        Graphics2D g = getGraphics2d(); - -        // save old color -        Color c = g.getColor(); - -        Composite composite = g.getComposite(); - -        // get the alpha from the color -        int alpha = color >>> 24; -        float falpha = alpha / 255.f; - -        setModeInGraphics(mode, g, falpha); - -        g.setColor(new Color(color)); - -        g.fillRect(0, 0, getWidth(), getHeight()); - -        g.setComposite(composite); - -        // restore color -        g.setColor(c); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawColor(int) -     */ -    @Override -    public void drawColor(int color) { -        drawColor(color, PorterDuff.Mode.SRC_OVER); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawARGB(int, int, int, int) -     */ -    @Override -    public void drawARGB(int a, int r, int g, int b) { -        drawColor(a << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawRGB(int, int, int) -     */ -    @Override -    public void drawRGB(int r, int g, int b) { -        drawColor(0xFF << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); -    } - - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#getWidth() -     */ -    @Override -    public int getWidth() { -        return mBufferedImage.getWidth(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#getHeight() -     */ -    @Override -    public int getHeight() { -        return mBufferedImage.getHeight(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPaint(android.graphics.Paint) -     */ -    @Override -    public void drawPaint(Paint paint) { -        drawColor(paint.getColor()); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { -        drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), -                (int)left, (int)top, -                (int)left+bitmap.getWidth(), (int)top+bitmap.getHeight(), paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint) -     */ -    @Override -    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { -        boolean needsRestore = false; -        if (matrix.isIdentity() == false) { -            // create a new graphics and apply the matrix to it -            save(); // this creates a new Graphics2D, and stores it for children call to use -            needsRestore = true; -            Graphics2D g = getGraphics2d(); // get the newly create Graphics2D - -            // get the Graphics2D current matrix -            AffineTransform currentTx = g.getTransform(); -            // get the AffineTransform from the matrix -            AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(matrix); - -            // combine them so that the matrix is applied after. -            currentTx.preConcatenate(matrixTx); - -            // give it to the graphics as a new matrix replacing all previous transform -            g.setTransform(currentTx); -        } - -        // draw the bitmap -        drawBitmap(bitmap, 0, 0, paint); - -        if (needsRestore) { -            // remove the new graphics -            restore(); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint) -     */ -    @Override -    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { -        if (src == null) { -            drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), -                    dst.left, dst.top, dst.right, dst.bottom, paint); -        } else { -            drawBitmap(bitmap, src.left, src.top, src.width(), src.height(), -                    dst.left, dst.top, dst.right, dst.bottom, paint); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint) -     */ -    @Override -    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { -        if (src == null) { -            drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), -                    (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint); -        } else { -            drawBitmap(bitmap, src.left, src.top, src.width(), src.height(), -                    (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint) -     */ -    @Override -    public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, -            int height, boolean hasAlpha, Paint paint) { -        throw new UnsupportedOperationException(); -    } - -    private void drawBitmap(Bitmap bitmap, int sleft, int stop, int sright, int sbottom, int dleft, -            int dtop, int dright, int dbottom, Paint paint) { -        BufferedImage image = Bitmap_Delegate.getImage(bitmap); - -        Graphics2D g = getGraphics2d(); - -        Composite c = null; - -        if (paint != null) { -            if (paint.isFilterBitmap()) { -                g = (Graphics2D)g.create(); -                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, -                        RenderingHints.VALUE_INTERPOLATION_BILINEAR); -            } - -            if (paint.getAlpha() != 0xFF) { -                c = g.getComposite(); -                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, -                        paint.getAlpha()/255.f)); -            } -        } - -        g.drawImage(image, dleft, dtop, dright, dbottom, -                sleft, stop, sright, sbottom, null); - -        if (paint != null) { -            if (paint.isFilterBitmap()) { -                g.dispose(); -            } -            if (c != null) { -                g.setComposite(c); -            } -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#rotate(float, float, float) -     */ -    @Override -    public void rotate(float degrees, float px, float py) { -        if (degrees != 0) { -            Graphics2D g = getGraphics2d(); -            g.translate(px, py); -            g.rotate(Math.toRadians(degrees)); -            g.translate(-px, -py); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#rotate(float) -     */ -    @Override -    public void rotate(float degrees) { -        getGraphics2d().rotate(Math.toRadians(degrees)); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#scale(float, float, float, float) -     */ -    @Override -    public void scale(float sx, float sy, float px, float py) { -        Graphics2D g = getGraphics2d(); -        g.translate(px, py); -        g.scale(sx, sy); -        g.translate(-px, -py); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#scale(float, float) -     */ -    @Override -    public void scale(float sx, float sy) { -        getGraphics2d().scale(sx, sy); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { -        // WARNING: the logic in this method is similar to Paint.measureText. -        // Any change to this method should be reflected in Paint.measureText -        Graphics2D g = getGraphics2d(); - -        g = (Graphics2D)g.create(); -        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - -        // set the color. because this only handles RGB, the alpha channel is handled -        // as a composite. -        g.setColor(new Color(paint.getColor())); -        int alpha = paint.getAlpha(); -        float falpha = alpha / 255.f; -        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); - - -        // Paint.TextAlign indicates how the text is positioned relative to X. -        // LEFT is the default and there's nothing to do. -        if (paint.getTextAlign() != Align.LEFT) { -            float m = paint.measureText(text, index, count); -            if (paint.getTextAlign() == Align.CENTER) { -                x -= m / 2; -            } else if (paint.getTextAlign() == Align.RIGHT) { -                x -= m; -            } -        } - -        List<FontInfo> fonts = paint.getFonts(); -        try { -            if (fonts.size() > 0) { -                FontInfo mainFont = fonts.get(0); -                int i = index; -                int lastIndex = index + count; -                while (i < lastIndex) { -                    // always start with the main font. -                    int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); -                    if (upTo == -1) { -                        // draw all the rest and exit. -                        g.setFont(mainFont.mFont); -                        g.drawChars(text, i, lastIndex - i, (int)x, (int)y); -                        return; -                    } else if (upTo > 0) { -                        // draw what's possible -                        g.setFont(mainFont.mFont); -                        g.drawChars(text, i, upTo - i, (int)x, (int)y); - -                        // compute the width that was drawn to increase x -                        x += mainFont.mMetrics.charsWidth(text, i, upTo - i); - -                        // move index to the first non displayed char. -                        i = upTo; - -                        // don't call continue at this point. Since it is certain the main font -                        // cannot display the font a index upTo (now ==i), we move on to the -                        // fallback fonts directly. -                    } - -                    // no char supported, attempt to read the next char(s) with the -                    // fallback font. In this case we only test the first character -                    // and then go back to test with the main font. -                    // Special test for 2-char characters. -                    boolean foundFont = false; -                    for (int f = 1 ; f < fonts.size() ; f++) { -                        FontInfo fontInfo = fonts.get(f); - -                        // need to check that the font can display the character. We test -                        // differently if the char is a high surrogate. -                        int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; -                        upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); -                        if (upTo == -1) { -                            // draw that char -                            g.setFont(fontInfo.mFont); -                            g.drawChars(text, i, charCount, (int)x, (int)y); - -                            // update x -                            x += fontInfo.mMetrics.charsWidth(text, i, charCount); - -                            // update the index in the text, and move on -                            i += charCount; -                            foundFont = true; -                            break; - -                        } -                    } - -                    // in case no font can display the char, display it with the main font. -                    // (it'll put a square probably) -                    if (foundFont == false) { -                        int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; - -                        g.setFont(mainFont.mFont); -                        g.drawChars(text, i, charCount, (int)x, (int)y); - -                        // measure it to advance x -                        x += mainFont.mMetrics.charsWidth(text, i, charCount); - -                        // and move to the next chars. -                        i += charCount; -                    } -                } -            } -        } finally { -            g.dispose(); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { -        drawText(text.toString().toCharArray(), start, end - start, x, y, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawText(java.lang.String, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawText(String text, float x, float y, Paint paint) { -        drawText(text.toCharArray(), 0, text.length(), x, y, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawText(java.lang.String, int, int, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawText(String text, int start, int end, float x, float y, Paint paint) { -        drawText(text.toCharArray(), start, end - start, x, y, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawRect(android.graphics.RectF, android.graphics.Paint) -     */ -    @Override -    public void drawRect(RectF rect, Paint paint) { -        doDrawRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawRect(float, float, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawRect(float left, float top, float right, float bottom, Paint paint) { -        doDrawRect((int)left, (int)top, (int)(right-left), (int)(bottom-top), paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawRect(android.graphics.Rect, android.graphics.Paint) -     */ -    @Override -    public void drawRect(Rect r, Paint paint) { -        doDrawRect(r.left, r.top, r.width(), r.height(), paint); -    } - -    private final void doDrawRect(int left, int top, int width, int height, Paint paint) { -        if (width > 0 && height > 0) { -            // get a Graphics2D object configured with the drawing parameters. -            Graphics2D g = getCustomGraphics(paint); - -            Style style = paint.getStyle(); - -            // draw -            if (style == Style.FILL || style == Style.FILL_AND_STROKE) { -                g.fillRect(left, top, width, height); -            } - -            if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { -                g.drawRect(left, top, width, height); -            } - -            // dispose Graphics2D object -            g.dispose(); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { -        if (rect.width() > 0 && rect.height() > 0) { -            // get a Graphics2D object configured with the drawing parameters. -            Graphics2D g = getCustomGraphics(paint); - -            Style style = paint.getStyle(); - -            // draw - -            int arcWidth = (int)(rx * 2); -            int arcHeight = (int)(ry * 2); - -            if (style == Style.FILL || style == Style.FILL_AND_STROKE) { -                g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), -                        arcWidth, arcHeight); -            } - -            if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { -                g.drawRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), -                        arcWidth, arcHeight); -            } - -            // dispose Graphics2D object -            g.dispose(); -        } -    } - - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawLine(float, float, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { -        // get a Graphics2D object configured with the drawing parameters. -        Graphics2D g = getCustomGraphics(paint); - -        g.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY); - -        // dispose Graphics2D object -        g.dispose(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawLines(float[], int, int, android.graphics.Paint) -     */ -    @Override -    public void drawLines(float[] pts, int offset, int count, Paint paint) { -        // get a Graphics2D object configured with the drawing parameters. -        Graphics2D g = getCustomGraphics(paint); - -        for (int i = 0 ; i < count ; i += 4) { -            g.drawLine((int)pts[i + offset], (int)pts[i + offset + 1], -                    (int)pts[i + offset + 2], (int)pts[i + offset + 3]); -        } - -        // dispose Graphics2D object -        g.dispose(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawLines(float[], android.graphics.Paint) -     */ -    @Override -    public void drawLines(float[] pts, Paint paint) { -        drawLines(pts, 0, pts.length, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawCircle(float, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawCircle(float cx, float cy, float radius, Paint paint) { -        // get a Graphics2D object configured with the drawing parameters. -        Graphics2D g = getCustomGraphics(paint); - -        Style style = paint.getStyle(); - -        int size = (int)(radius * 2); - -        // draw -        if (style == Style.FILL || style == Style.FILL_AND_STROKE) { -            g.fillOval((int)(cx - radius), (int)(cy - radius), size, size); -        } - -        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { -            g.drawOval((int)(cx - radius), (int)(cy - radius), size, size); -        } - -        // dispose Graphics2D object -        g.dispose(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawOval(android.graphics.RectF, android.graphics.Paint) -     */ -    @Override -    public void drawOval(RectF oval, Paint paint) { -        // get a Graphics2D object configured with the drawing parameters. -        Graphics2D g = getCustomGraphics(paint); - -        Style style = paint.getStyle(); - -        // draw -        if (style == Style.FILL || style == Style.FILL_AND_STROKE) { -            g.fillOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height()); -        } - -        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { -            g.drawOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height()); -        } - -        // dispose Graphics2D object -        g.dispose(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPath(android.graphics.Path, android.graphics.Paint) -     */ -    @Override -    public void drawPath(Path path, Paint paint) { -        // get a Graphics2D object configured with the drawing parameters. -        Graphics2D g = getCustomGraphics(paint); - -        Style style = paint.getStyle(); - -        // draw -        if (style == Style.FILL || style == Style.FILL_AND_STROKE) { -            g.fill(path.getAwtShape()); -        } - -        if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { -            g.draw(path.getAwtShape()); -        } - -        // dispose Graphics2D object -        g.dispose(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#setMatrix(android.graphics.Matrix) -     */ -    @Override -    public void setMatrix(Matrix matrix) { -        // get the new current graphics -        Graphics2D g = getGraphics2d(); - -        // and apply the matrix -        g.setTransform(Matrix_Delegate.getAffineTransform(matrix)); - -        if (mLogger != null && Matrix_Delegate.hasPerspective(matrix)) { -            mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor."); -        } -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#concat(android.graphics.Matrix) -     */ -    @Override -    public void concat(Matrix matrix) { -        // get the current top graphics2D object. -        Graphics2D g = getGraphics2d(); - -        // get its current matrix -        AffineTransform currentTx = g.getTransform(); -        // get the AffineTransform of the given matrix -        AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(matrix); - -        // combine them so that the given matrix is applied after. -        currentTx.preConcatenate(matrixTx); - -        // give it to the graphics2D as a new matrix replacing all previous transform -        g.setTransform(currentTx); -    } - - -    // -------------------- - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipPath(android.graphics.Path, android.graphics.Region.Op) -     */ -    @Override -    public boolean clipPath(Path path, Op op) { -        // TODO Auto-generated method stub -        return super.clipPath(path, op); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipPath(android.graphics.Path) -     */ -    @Override -    public boolean clipPath(Path path) { -        // TODO Auto-generated method stub -        return super.clipPath(path); -    } - - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRegion(android.graphics.Region, android.graphics.Region.Op) -     */ -    @Override -    public boolean clipRegion(Region region, Op op) { -        // TODO Auto-generated method stub -        return super.clipRegion(region, op); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#clipRegion(android.graphics.Region) -     */ -    @Override -    public boolean clipRegion(Region region) { -        // TODO Auto-generated method stub -        return super.clipRegion(region); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint) -     */ -    @Override -    public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, -            Paint paint) { -        // TODO Auto-generated method stub -        super.drawArc(oval, startAngle, sweepAngle, useCenter, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint) -     */ -    @Override -    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, -            int vertOffset, int[] colors, int colorOffset, Paint paint) { -        // TODO Auto-generated method stub -        super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.Rect) -     */ -    @Override -    public void drawPicture(Picture picture, Rect dst) { -        // TODO Auto-generated method stub -        super.drawPicture(picture, dst); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.RectF) -     */ -    @Override -    public void drawPicture(Picture picture, RectF dst) { -        // TODO Auto-generated method stub -        super.drawPicture(picture, dst); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPicture(android.graphics.Picture) -     */ -    @Override -    public void drawPicture(Picture picture) { -        // TODO Auto-generated method stub -        super.drawPicture(picture); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPoint(float, float, android.graphics.Paint) -     */ -    @Override -    public void drawPoint(float x, float y, Paint paint) { -        // TODO Auto-generated method stub -        super.drawPoint(x, y, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPoints(float[], int, int, android.graphics.Paint) -     */ -    @Override -    public void drawPoints(float[] pts, int offset, int count, Paint paint) { -        // TODO Auto-generated method stub -        super.drawPoints(pts, offset, count, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPoints(float[], android.graphics.Paint) -     */ -    @Override -    public void drawPoints(float[] pts, Paint paint) { -        // TODO Auto-generated method stub -        super.drawPoints(pts, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPosText(char[], int, int, float[], android.graphics.Paint) -     */ -    @Override -    public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { -        // TODO Auto-generated method stub -        super.drawPosText(text, index, count, pos, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawPosText(java.lang.String, float[], android.graphics.Paint) -     */ -    @Override -    public void drawPosText(String text, float[] pos, Paint paint) { -        // TODO Auto-generated method stub -        super.drawPosText(text, pos, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawTextOnPath(char[] text, int index, int count, Path path, float offset, -            float offset2, Paint paint) { -        // TODO Auto-generated method stub -        super.drawTextOnPath(text, index, count, path, offset, offset2, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint) -     */ -    @Override -    public void drawTextOnPath(String text, Path path, float offset, float offset2, Paint paint) { -        // TODO Auto-generated method stub -        super.drawTextOnPath(text, path, offset, offset2, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#drawVertices(android.graphics.Canvas.VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint) -     */ -    @Override -    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, -            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, -            int indexOffset, int indexCount, Paint paint) { -        // TODO Auto-generated method stub -        super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, colorOffset, -                indices, indexOffset, indexCount, paint); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#getDrawFilter() -     */ -    @Override -    public DrawFilter getDrawFilter() { -        // TODO Auto-generated method stub -        return super.getDrawFilter(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#getMatrix() -     */ -    @Override -    public Matrix getMatrix() { -        // TODO Auto-generated method stub -        return super.getMatrix(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#getMatrix(android.graphics.Matrix) -     */ -    @Override -    public void getMatrix(Matrix ctm) { -        // TODO Auto-generated method stub -        super.getMatrix(ctm); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#isOpaque() -     */ -    @Override -    public boolean isOpaque() { -        // TODO Auto-generated method stub -        return super.isOpaque(); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#saveLayer(float, float, float, float, android.graphics.Paint, int) -     */ -    @Override -    public int saveLayer(float left, float top, float right, float bottom, Paint paint, -            int saveFlags) { -        // TODO Auto-generated method stub -        return super.saveLayer(left, top, right, bottom, paint, saveFlags); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#saveLayer(android.graphics.RectF, android.graphics.Paint, int) -     */ -    @Override -    public int saveLayer(RectF bounds, Paint paint, int saveFlags) { -        // TODO Auto-generated method stub -        return super.saveLayer(bounds, paint, saveFlags); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#saveLayerAlpha(float, float, float, float, int, int) -     */ -    @Override -    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, -            int saveFlags) { -        // TODO Auto-generated method stub -        return super.saveLayerAlpha(left, top, right, bottom, alpha, saveFlags); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#saveLayerAlpha(android.graphics.RectF, int, int) -     */ -    @Override -    public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { -        // TODO Auto-generated method stub -        return super.saveLayerAlpha(bounds, alpha, saveFlags); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#setDrawFilter(android.graphics.DrawFilter) -     */ -    @Override -    public void setDrawFilter(DrawFilter filter) { -        // TODO Auto-generated method stub -        super.setDrawFilter(filter); -    } - -    /* (non-Javadoc) -     * @see android.graphics.Canvas#skew(float, float) -     */ -    @Override -    public void skew(float sx, float sy) { -        // TODO Auto-generated method stub -        super.skew(sx, sy); -    } - - - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java new file mode 100644 index 000000000000..6627d370cf89 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -0,0 +1,559 @@ +/* + * Copyright (C) 2010 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 android.graphics; + +import com.android.layoutlib.api.ILayoutLog; +import com.android.layoutlib.bridge.DelegateManager; + +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.util.Stack; + +/** + * Delegate implementing the native methods of android.graphics.Canvas + * + * Through the layoutlib_create tool, the original native methods of Canvas have been replaced + * by calls to methods of the same name in this delegate class. + * + * This class behaves like the original native implementation, but in Java, keeping previously + * native data into its own objects and mapping them to int that are sent back and forth between + * it and the original Canvas class. + * + * @see DelegateManager + * + */ +public class Canvas_Delegate { + +    // ---- delegate manager ---- +    private static final DelegateManager<Canvas_Delegate> sManager = +            new DelegateManager<Canvas_Delegate>(); + +    // ---- delegate helper data ---- + +    // ---- delegate data ---- +    private BufferedImage mBufferedImage; +    private final Stack<Graphics2D> mGraphicsStack = new Stack<Graphics2D>(); +    private ILayoutLog mLogger; + +    // ---- Public Helper methods ---- + +    /** +     * Returns the native delegate associated to a given {@link Canvas} object. +     */ +    public static Canvas_Delegate getDelegate(Canvas canvas) { +        return sManager.getDelegate(canvas.mNativeCanvas); +    } + +    /** +     * Returns the native delegate associated to a given an int referencing a {@link Canvas} object. +     */ +    public static Canvas_Delegate getDelegate(int native_canvas) { +        return sManager.getDelegate(native_canvas); +    } + +    /** +     * Sets the layoutlib logger into the canvas. +     * @param logger +     */ +    public void setLogger(ILayoutLog logger) { +        mLogger = logger; +    } + +    /** +     * Returns the current {@link Graphics2D} used to draw. +     */ +    public Graphics2D getGraphics2d() { +        return mGraphicsStack.peek(); +    } + +    /** +     * Disposes of the {@link Graphics2D} stack. +     */ +    public void dispose() { + +    } + +    // ---- native methods ---- + +    /*package*/ static boolean isOpaque(Canvas thisCanvas) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int getWidth(Canvas thisCanvas) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int getHeight(Canvas thisCanvas) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void translate(Canvas thisCanvas, float dx, float dy) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void rotate(Canvas thisCanvas, float degrees) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void scale(Canvas thisCanvas, float sx, float sy) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void skew(Canvas thisCanvas, float sx, float sy) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean clipRect(Canvas thisCanvas, RectF rect) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean clipRect(Canvas thisCanvas, Rect rect) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean clipRect(Canvas thisCanvas, float left, float top, float right, +            float bottom) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean clipRect(Canvas thisCanvas, int left, int top, int right, +            int bottom) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int save(Canvas thisCanvas) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int save(Canvas thisCanvas, int saveFlags) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void restore(Canvas thisCanvas) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int getSaveCount(Canvas thisCanvas) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void drawPoints(Canvas thisCanvas, float[] pts, int offset, int count, +            Paint paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void drawPoint(Canvas thisCanvas, float x, float y, Paint paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void drawLines(Canvas thisCanvas, float[] pts, int offset, int count, +            Paint paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void freeCaches() { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int initRaster(int nativeBitmapOrZero) { +        if (nativeBitmapOrZero > 0) { +            // get the Bitmap from the int +            Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero); + +            // create a new Canvas_Delegate with the given bitmap and return its new native int. +            Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate.getImage()); + +            return sManager.addDelegate(newDelegate); +        } else { +            // create a new Canvas_Delegate and return its new native int. +            Canvas_Delegate newDelegate = new Canvas_Delegate(); + +            return sManager.addDelegate(newDelegate); +        } +    } + +    /*package*/ static void native_setBitmap(int nativeCanvas, int bitmap) { +        // get the delegate from the native int. +        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); +        if (canvasDelegate == null) { +            assert false; +            return; +        } + +        // get the delegate from the native int. +        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); +        if (bitmapDelegate == null) { +            assert false; +            return; +        } + +        canvasDelegate.setBitmap(bitmapDelegate.getImage()); +    } + +    /*package*/ static int native_saveLayer(int nativeCanvas, RectF bounds, +                                               int paint, int layerFlags) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_saveLayer(int nativeCanvas, float l, +                                               float t, float r, float b, +                                               int paint, int layerFlags) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_saveLayerAlpha(int nativeCanvas, +                                                    RectF bounds, int alpha, +                                                    int layerFlags) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_saveLayerAlpha(int nativeCanvas, float l, +                                                    float t, float r, float b, +                                                    int alpha, int layerFlags) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + + +    /*package*/ static void native_concat(int nCanvas, int nMatrix) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_setMatrix(int nCanvas, int nMatrix) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean native_clipRect(int nCanvas, +                                                  float left, float top, +                                                  float right, float bottom, +                                                  int regionOp) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean native_clipPath(int nativeCanvas, +                                                  int nativePath, +                                                  int regionOp) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean native_clipRegion(int nativeCanvas, +                                                    int nativeRegion, +                                                    int regionOp) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void nativeSetDrawFilter(int nativeCanvas, +                                                   int nativeFilter) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean native_getClipBounds(int nativeCanvas, +                                                       Rect bounds) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_getCTM(int canvas, int matrix) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean native_quickReject(int nativeCanvas, +                                                     RectF rect, +                                                     int native_edgeType) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean native_quickReject(int nativeCanvas, +                                                     int path, +                                                     int native_edgeType) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static boolean native_quickReject(int nativeCanvas, +                                                     float left, float top, +                                                     float right, float bottom, +                                                     int native_edgeType) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawRGB(int nativeCanvas, int r, int g, +                                              int b) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawARGB(int nativeCanvas, int a, int r, +                                               int g, int b) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawColor(int nativeCanvas, int color) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawColor(int nativeCanvas, int color, +                                                int mode) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawPaint(int nativeCanvas, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawLine(int nativeCanvas, float startX, +                                               float startY, float stopX, +                                               float stopY, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawRect(int nativeCanvas, RectF rect, +                                               int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawRect(int nativeCanvas, float left, +                                               float top, float right, +                                               float bottom, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawOval(int nativeCanvas, RectF oval, +                                               int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawCircle(int nativeCanvas, float cx, +                                                 float cy, float radius, +                                                 int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawArc(int nativeCanvas, RectF oval, +                                              float startAngle, float sweep, +                                              boolean useCenter, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawRoundRect(int nativeCanvas, +                                                    RectF rect, float rx, +                                                    float ry, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawPath(int nativeCanvas, int path, +                                               int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap, +                                                 float left, float top, +                                                 int nativePaintOrZero, +                                                 int canvasDensity, +                                                 int screenDensity, +                                                 int bitmapDensity) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap, +                                                 Rect src, RectF dst, +                                                 int nativePaintOrZero, +                                                 int screenDensity, +                                                 int bitmapDensity) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawBitmap(int nativeCanvas, int bitmap, +                                                 Rect src, Rect dst, +                                                 int nativePaintOrZero, +                                                 int screenDensity, +                                                 int bitmapDensity) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawBitmap(int nativeCanvas, int[] colors, +                                                int offset, int stride, float x, +                                                 float y, int width, int height, +                                                 boolean hasAlpha, +                                                 int nativePaintOrZero) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void nativeDrawBitmapMatrix(int nCanvas, int nBitmap, +                                                      int nMatrix, int nPaint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void nativeDrawBitmapMesh(int nCanvas, int nBitmap, +                                                    int meshWidth, int meshHeight, +                                                    float[] verts, int vertOffset, +                                                    int[] colors, int colorOffset, int nPaint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void nativeDrawVertices(int nCanvas, int mode, int n, +                   float[] verts, int vertOffset, float[] texs, int texOffset, +                   int[] colors, int colorOffset, short[] indices, +                   int indexOffset, int indexCount, int nPaint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + + +    /*package*/ static void native_drawText(int nativeCanvas, char[] text, +                                               int index, int count, float x, +                                               float y, int flags, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawText(int nativeCanvas, String text, +                                               int start, int end, float x, +                                               float y, int flags, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + + +    /*package*/ static void native_drawTextRun(int nativeCanvas, String text, +            int start, int end, int contextStart, int contextEnd, +            float x, float y, int flags, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + + +    /*package*/ static void native_drawTextRun(int nativeCanvas, char[] text, +            int start, int count, int contextStart, int contextCount, +            float x, float y, int flags, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + + +    /*package*/ static void native_drawPosText(int nativeCanvas, +                                                  char[] text, int index, +                                                  int count, float[] pos, +                                                  int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawPosText(int nativeCanvas, +                                                  String text, float[] pos, +                                                  int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawTextOnPath(int nativeCanvas, +                                                     char[] text, int index, +                                                     int count, int path, +                                                     float hOffset, +                                                     float vOffset, int bidiFlags, +                                                     int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawTextOnPath(int nativeCanvas, +                                                     String text, int path, +                                                     float hOffset, +                                                     float vOffset, +                                                     int flags, int paint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_drawPicture(int nativeCanvas, +                                                  int nativePicture) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void finalizer(int nativeCanvas) { +        sManager.removeDelegate(nativeCanvas); +    } + +    // ---- Private delegate/helper methods ---- + +    private Canvas_Delegate(BufferedImage image) { +        setBitmap(image); +    } + +    private Canvas_Delegate() { +    } + +    private void setBitmap(BufferedImage image) { +        mBufferedImage = image; +        mGraphicsStack.push(mBufferedImage.createGraphics()); +    } +} diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint.java b/tools/layoutlib/bridge/src/android/graphics/Paint.java deleted file mode 100644 index 2de21c14d98d..000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Paint.java +++ /dev/null @@ -1,1211 +0,0 @@ -/* - * Copyright (C) 2008 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 android.graphics; - -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.SpannedString; -import android.text.TextUtils; - -import java.awt.BasicStroke; -import java.awt.Font; -import java.awt.Toolkit; -import java.awt.font.FontRenderContext; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A paint implementation overridden by the LayoutLib bridge. - */ -public class Paint extends _Original_Paint { - -    private int mColor = 0xFFFFFFFF; -    private float mStrokeWidth = 1.f; -    private float mTextSize = 20; -    private float mScaleX = 1; -    private float mSkewX = 0; -    private Align mAlign = Align.LEFT; -    private Style mStyle = Style.FILL; -    private float mStrokeMiter = 4.0f; -    private Cap mCap = Cap.BUTT; -    private Join mJoin = Join.MITER; -    private int mFlags = 0; - -    /** -     * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}. -     */ -    public static final class FontInfo { -        Font mFont; -        java.awt.FontMetrics mMetrics; -    } - -    private List<FontInfo> mFonts; -    private final FontRenderContext mFontContext = new FontRenderContext( -            new AffineTransform(), true, true); - -    public static final int ANTI_ALIAS_FLAG       = _Original_Paint.ANTI_ALIAS_FLAG; -    public static final int FILTER_BITMAP_FLAG    = _Original_Paint.FILTER_BITMAP_FLAG; -    public static final int DITHER_FLAG           = _Original_Paint.DITHER_FLAG; -    public static final int UNDERLINE_TEXT_FLAG   = _Original_Paint.UNDERLINE_TEXT_FLAG; -    public static final int STRIKE_THRU_TEXT_FLAG = _Original_Paint.STRIKE_THRU_TEXT_FLAG; -    public static final int FAKE_BOLD_TEXT_FLAG   = _Original_Paint.FAKE_BOLD_TEXT_FLAG; -    public static final int LINEAR_TEXT_FLAG      = _Original_Paint.LINEAR_TEXT_FLAG; -    public static final int SUBPIXEL_TEXT_FLAG    = _Original_Paint.SUBPIXEL_TEXT_FLAG; -    public static final int DEV_KERN_TEXT_FLAG    = _Original_Paint.DEV_KERN_TEXT_FLAG; - -    public static class FontMetrics extends _Original_Paint.FontMetrics { -    } - -    public static class FontMetricsInt extends _Original_Paint.FontMetricsInt { -    } - -    /** -     * The Style specifies if the primitive being drawn is filled, -     * stroked, or both (in the same color). The default is FILL. -     */ -    public enum Style { -        /** -         * Geometry and text drawn with this style will be filled, ignoring all -         * stroke-related settings in the paint. -         */ -        FILL            (0), -        /** -         * Geometry and text drawn with this style will be stroked, respecting -         * the stroke-related fields on the paint. -         */ -        STROKE          (1), -        /** -         * Geometry and text drawn with this style will be both filled and -         * stroked at the same time, respecting the stroke-related fields on -         * the paint. -         */ -        FILL_AND_STROKE (2); - -        Style(int nativeInt) { -            this.nativeInt = nativeInt; -        } -        final int nativeInt; -    } - -    /** -     * The Cap specifies the treatment for the beginning and ending of -     * stroked lines and paths. The default is BUTT. -     */ -    public enum Cap { -        /** -         * The stroke ends with the path, and does not project beyond it. -         */ -        BUTT    (0), -        /** -         * The stroke projects out as a square, with the center at the end -         * of the path. -         */ -        ROUND   (1), -        /** -         * The stroke projects out as a semicircle, with the center at the -         * end of the path. -         */ -        SQUARE  (2); - -        private Cap(int nativeInt) { -            this.nativeInt = nativeInt; -        } -        final int nativeInt; - -        /** custom for layoutlib */ -        public int getJavaCap() { -            switch (this) { -                case BUTT: -                    return BasicStroke.CAP_BUTT; -                case ROUND: -                    return BasicStroke.CAP_ROUND; -                default: -                case SQUARE: -                    return BasicStroke.CAP_SQUARE; -            } -        } -    } - -    /** -     * The Join specifies the treatment where lines and curve segments -     * join on a stroked path. The default is MITER. -     */ -    public enum Join { -        /** -         * The outer edges of a join meet at a sharp angle -         */ -        MITER   (0), -        /** -         * The outer edges of a join meet in a circular arc. -         */ -        ROUND   (1), -        /** -         * The outer edges of a join meet with a straight line -         */ -        BEVEL   (2); - -        private Join(int nativeInt) { -            this.nativeInt = nativeInt; -        } -        final int nativeInt; - -        /** custom for layoutlib */ -        public int getJavaJoin() { -            switch (this) { -                default: -                case MITER: -                    return BasicStroke.JOIN_MITER; -                case ROUND: -                    return BasicStroke.JOIN_ROUND; -                case BEVEL: -                    return BasicStroke.JOIN_BEVEL; -            } -        } -    } - -    /** -     * Align specifies how drawText aligns its text relative to the -     * [x,y] coordinates. The default is LEFT. -     */ -    public enum Align { -        /** -         * The text is drawn to the right of the x,y origin -         */ -        LEFT    (0), -        /** -         * The text is drawn centered horizontally on the x,y origin -         */ -        CENTER  (1), -        /** -         * The text is drawn to the left of the x,y origin -         */ -        RIGHT   (2); - -        private Align(int nativeInt) { -            this.nativeInt = nativeInt; -        } -        final int nativeInt; -    } - -    public Paint() { -        this(0); -    } - -    /* -     * Do not remove or com.android.layoutlib.bridge.TestClassReplacement fails. -     */ -    @Override -    public void finalize() { } - -    public Paint(int flags) { -        setFlags(flags | DEFAULT_PAINT_FLAGS); -        initFont(); -    } - -    public Paint(Paint paint) { -        set(paint); -        initFont(); -    } - -    @Override -    public void reset() { -        super.reset(); -    } - -    /** -     * Returns the list of {@link Font} objects. The first item is the main font, the rest -     * are fall backs for characters not present in the main font. -     */ -    public List<FontInfo> getFonts() { -        return mFonts; -    } - -    private void initFont() { -        mTypeface = Typeface.DEFAULT; -        updateFontObject(); -    } - -    /** -     * Update the {@link Font} object from the typeface, text size and scaling -     */ -    @SuppressWarnings("deprecation") -    private void updateFontObject() { -        if (mTypeface != null) { -            // Get the fonts from the TypeFace object. -            List<Font> fonts = Typeface_Delegate.getFonts(mTypeface); - -            // create new font objects as well as FontMetrics, based on the current text size -            // and skew info. -            ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size()); -            for (Font font : fonts) { -                FontInfo info = new FontInfo(); -                info.mFont = font.deriveFont(mTextSize); -                if (mScaleX != 1.0 || mSkewX != 0) { -                    // TODO: support skew -                    info.mFont = info.mFont.deriveFont(new AffineTransform( -                            mScaleX, mSkewX, 0, 0, 1, 0)); -                } -                info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont); - -                infoList.add(info); -            } - -            mFonts = Collections.unmodifiableList(infoList); -        } -    } - -    //---------------------------------------- - -    public void set(Paint src) { -        if (this != src) { -            mColor = src.mColor; -            mTextSize = src.mTextSize; -            mScaleX = src.mScaleX; -            mSkewX = src.mSkewX; -            mAlign = src.mAlign; -            mStyle = src.mStyle; -            mFlags = src.mFlags; - -            updateFontObject(); - -            super.set(src); -        } -    } - -    @Override -    public void setCompatibilityScaling(float factor) { -        super.setCompatibilityScaling(factor); -    } - -    @Override -    public int getFlags() { -        return mFlags; -    } - -    @Override -    public void setFlags(int flags) { -        mFlags = flags; -    } - -    @Override -    public boolean isAntiAlias() { -        return super.isAntiAlias(); -    } - -    @Override -    public boolean isDither() { -        return super.isDither(); -    } - -    @Override -    public boolean isLinearText() { -        return super.isLinearText(); -    } - -    @Override -    public boolean isStrikeThruText() { -        return super.isStrikeThruText(); -    } - -    @Override -    public boolean isUnderlineText() { -        return super.isUnderlineText(); -    } - -    @Override -    public boolean isFakeBoldText() { -        return super.isFakeBoldText(); -    } - -    @Override -    public boolean isSubpixelText() { -        return super.isSubpixelText(); -    } - -    @Override -    public boolean isFilterBitmap() { -        return super.isFilterBitmap(); -    } - -    /** -     * Return the font's recommended interline spacing, given the Paint's -     * settings for typeface, textSize, etc. If metrics is not null, return the -     * fontmetric values in it. -     * -     * @param metrics If this object is not null, its fields are filled with -     *                the appropriate values given the paint's text attributes. -     * @return the font's recommended interline spacing. -     */ -    public float getFontMetrics(FontMetrics metrics) { -        if (mFonts.size() > 0) { -            java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; -            if (metrics != null) { -                // Android expects negative ascent so we invert the value from Java. -                metrics.top = - javaMetrics.getMaxAscent(); -                metrics.ascent = - javaMetrics.getAscent(); -                metrics.descent = javaMetrics.getDescent(); -                metrics.bottom = javaMetrics.getMaxDescent(); -                metrics.leading = javaMetrics.getLeading(); -            } - -            return javaMetrics.getHeight(); -        } - -        return 0; -    } - -    public int getFontMetricsInt(FontMetricsInt metrics) { -        if (mFonts.size() > 0) { -            java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; -            if (metrics != null) { -                // Android expects negative ascent so we invert the value from Java. -                metrics.top = - javaMetrics.getMaxAscent(); -                metrics.ascent = - javaMetrics.getAscent(); -                metrics.descent = javaMetrics.getDescent(); -                metrics.bottom = javaMetrics.getMaxDescent(); -                metrics.leading = javaMetrics.getLeading(); -            } - -            return javaMetrics.getHeight(); -        } - -        return 0; -    } - -    /** -     * Reimplemented to return Paint.FontMetrics instead of _Original_Paint.FontMetrics -     */ -    public FontMetrics getFontMetrics() { -        FontMetrics fm = new FontMetrics(); -        getFontMetrics(fm); -        return fm; -    } - -    /** -     * Reimplemented to return Paint.FontMetricsInt instead of _Original_Paint.FontMetricsInt -     */ -    public FontMetricsInt getFontMetricsInt() { -        FontMetricsInt fm = new FontMetricsInt(); -        getFontMetricsInt(fm); -        return fm; -    } - - - -    @Override -    public float getFontMetrics(_Original_Paint.FontMetrics metrics) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    @Override -    public int getFontMetricsInt(_Original_Paint.FontMetricsInt metrics) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    @Override -    public Typeface setTypeface(Typeface typeface) { -        if (typeface != null) { -            mTypeface = typeface; -        } else { -            mTypeface = Typeface.DEFAULT; -        } - -        updateFontObject(); - -        return typeface; -    } - -    @Override -    public Typeface getTypeface() { -        return super.getTypeface(); -    } - -    @Override -    public int getColor() { -        return mColor; -    } - -    @Override -    public void setColor(int color) { -        mColor = color; -    } - -    @Override -    public void setARGB(int a, int r, int g, int b) { -        super.setARGB(a, r, g, b); -    } - -    @Override -    public void setAlpha(int alpha) { -        mColor = (alpha << 24) | (mColor & 0x00FFFFFF); -    } - -    @Override -    public int getAlpha() { -        return mColor >>> 24; -    } - -    /** -     * Set or clear the shader object. -     * <p /> -     * Pass null to clear any previous shader. -     * As a convenience, the parameter passed is also returned. -     * -     * @param shader May be null. the new shader to be installed in the paint -     * @return       shader -     */ -    @Override -    public Shader setShader(Shader shader) { -        return mShader = shader; -    } - -    @Override -    public Shader getShader() { -        return super.getShader(); -    } - -    /** -     * Set or clear the paint's colorfilter, returning the parameter. -     * -     * @param filter May be null. The new filter to be installed in the paint -     * @return       filter -     */ -    @Override -    public ColorFilter setColorFilter(ColorFilter filter) { -        mColorFilter = filter; -        return filter; -    } - -    @Override -    public ColorFilter getColorFilter() { -        return super.getColorFilter(); -    } - -    /** -     * Set or clear the xfermode object. -     * <p /> -     * Pass null to clear any previous xfermode. -     * As a convenience, the parameter passed is also returned. -     * -     * @param xfermode May be null. The xfermode to be installed in the paint -     * @return         xfermode -     */ -    @Override -    public Xfermode setXfermode(Xfermode xfermode) { -        return mXfermode = xfermode; -    } - -    @Override -    public Xfermode getXfermode() { -        return super.getXfermode(); -    } - -    @Override -    public Rasterizer setRasterizer(Rasterizer rasterizer) { -        mRasterizer = rasterizer; -        return rasterizer; -    } - -    @Override -    public Rasterizer getRasterizer() { -        return super.getRasterizer(); -    } - -    @Override -    public void setShadowLayer(float radius, float dx, float dy, int color) { -        // TODO Auto-generated method stub -    } - -    @Override -    public void clearShadowLayer() { -        super.clearShadowLayer(); -    } - -    public void setTextAlign(Align align) { -        mAlign = align; -    } - -    @Override -    public void setTextAlign(android.graphics._Original_Paint.Align align) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    public Align getTextAlign() { -        return mAlign; -    } - -    public void setStyle(Style style) { -        mStyle = style; -    } - -    @Override -    public void setStyle(android.graphics._Original_Paint.Style style) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    public Style getStyle() { -        return mStyle; -    } - -    @Override -    public void setDither(boolean dither) { -        mFlags |= dither ? DITHER_FLAG : ~DITHER_FLAG; -    } - -    @Override -    public void setAntiAlias(boolean aa) { -        mFlags |= aa ? ANTI_ALIAS_FLAG : ~ANTI_ALIAS_FLAG; -    } - -    @Override -    public void setFakeBoldText(boolean flag) { -        mFlags |= flag ? FAKE_BOLD_TEXT_FLAG : ~FAKE_BOLD_TEXT_FLAG; -    } - -    @Override -    public void setLinearText(boolean flag) { -        mFlags |= flag ? LINEAR_TEXT_FLAG : ~LINEAR_TEXT_FLAG; -    } - -    @Override -    public void setSubpixelText(boolean flag) { -        mFlags |= flag ? SUBPIXEL_TEXT_FLAG : ~SUBPIXEL_TEXT_FLAG; -    } - -    @Override -    public void setUnderlineText(boolean flag) { -        mFlags |= flag ? UNDERLINE_TEXT_FLAG : ~UNDERLINE_TEXT_FLAG; -    } - -    @Override -    public void setStrikeThruText(boolean flag) { -        mFlags |= flag ? STRIKE_THRU_TEXT_FLAG : ~STRIKE_THRU_TEXT_FLAG; -    } - -    @Override -    public void setFilterBitmap(boolean flag) { -        mFlags |= flag ? FILTER_BITMAP_FLAG : ~FILTER_BITMAP_FLAG; -    } - -    @Override -    public float getStrokeWidth() { -        return mStrokeWidth; -    } - -    @Override -    public void setStrokeWidth(float width) { -        mStrokeWidth = width; -    } - -    @Override -    public float getStrokeMiter() { -        return mStrokeMiter; -    } - -    @Override -    public void setStrokeMiter(float miter) { -        mStrokeMiter = miter; -    } - -    @Override -    public void setStrokeCap(android.graphics._Original_Paint.Cap cap) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    public void setStrokeCap(Cap cap) { -        mCap = cap; -    } - -    public Cap getStrokeCap() { -        return mCap; -    } - -    @Override -    public void setStrokeJoin(android.graphics._Original_Paint.Join join) { -        throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); -    } - -    public void setStrokeJoin(Join join) { -        mJoin = join; -    } - -    public Join getStrokeJoin() { -        return mJoin; -    } - -    @Override -    public boolean getFillPath(Path src, Path dst) { -        return super.getFillPath(src, dst); -    } - -    @Override -    public PathEffect setPathEffect(PathEffect effect) { -        mPathEffect = effect; -        return effect; -    } - -    @Override -    public PathEffect getPathEffect() { -        return super.getPathEffect(); -    } - -    @Override -    public MaskFilter setMaskFilter(MaskFilter maskfilter) { -        mMaskFilter = maskfilter; -        return maskfilter; -    } - -    @Override -    public MaskFilter getMaskFilter() { -        return super.getMaskFilter(); -    } - -    /** -     * Return the paint's text size. -     * -     * @return the paint's text size. -     */ -    @Override -    public float getTextSize() { -        return mTextSize; -    } - -    /** -     * Set the paint's text size. This value must be > 0 -     * -     * @param textSize set the paint's text size. -     */ -    @Override -    public void setTextSize(float textSize) { -        mTextSize = textSize; - -        updateFontObject(); -    } - -    /** -     * Return the paint's horizontal scale factor for text. The default value -     * is 1.0. -     * -     * @return the paint's scale factor in X for drawing/measuring text -     */ -    @Override -    public float getTextScaleX() { -        return mScaleX; -    } - -    /** -     * Set the paint's horizontal scale factor for text. The default value -     * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will -     * stretch the text narrower. -     * -     * @param scaleX set the paint's scale in X for drawing/measuring text. -     */ -    @Override -    public void setTextScaleX(float scaleX) { -        mScaleX = scaleX; - -        updateFontObject(); -    } - -    /** -     * Return the paint's horizontal skew factor for text. The default value -     * is 0. -     * -     * @return         the paint's skew factor in X for drawing text. -     */ -    @Override -    public float getTextSkewX() { -        return mSkewX; -    } - -    /** -     * Set the paint's horizontal skew factor for text. The default value -     * is 0. For approximating oblique text, use values around -0.25. -     * -     * @param skewX set the paint's skew factor in X for drawing text. -     */ -    @Override -    public void setTextSkewX(float skewX) { -        mSkewX = skewX; - -        updateFontObject(); -    } - -    @Override -    public float getFontSpacing() { -        return super.getFontSpacing(); -    } - -    /** -     * Return the distance above (negative) the baseline (ascent) based on the -     * current typeface and text size. -     * -     * @return the distance above (negative) the baseline (ascent) based on the -     *         current typeface and text size. -     */ -    @Override -    public float ascent() { -        if (mFonts.size() > 0) { -            java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; -            // Android expects negative ascent so we invert the value from Java. -            return - javaMetrics.getAscent(); -        } - -        return 0; -    } - -    /** -     * Return the distance below (positive) the baseline (descent) based on the -     * current typeface and text size. -     * -     * @return the distance below (positive) the baseline (descent) based on -     *         the current typeface and text size. -     */ -    @Override -    public float descent() { -        if (mFonts.size() > 0) { -            java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; -            return javaMetrics.getDescent(); -        } - -        return 0; -    } - -    /** -     * Return the width of the text. -     * -     * @param text  The text to measure -     * @param index The index of the first character to start measuring -     * @param count THe number of characters to measure, beginning with start -     * @return      The width of the text -     */ -    @Override -    public float measureText(char[] text, int index, int count) { -        // WARNING: the logic in this method is similar to Canvas.drawText. -        // Any change to this method should be reflected in Canvas.drawText -        if (mFonts.size() > 0) { -            FontInfo mainFont = mFonts.get(0); -            int i = index; -            int lastIndex = index + count; -            float total = 0f; -            while (i < lastIndex) { -                // always start with the main font. -                int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); -                if (upTo == -1) { -                    // shortcut to exit -                    return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i); -                } else if (upTo > 0) { -                    total += mainFont.mMetrics.charsWidth(text, i, upTo - i); -                    i = upTo; -                    // don't call continue at this point. Since it is certain the main font -                    // cannot display the font a index upTo (now ==i), we move on to the -                    // fallback fonts directly. -                } - -                // no char supported, attempt to read the next char(s) with the -                // fallback font. In this case we only test the first character -                // and then go back to test with the main font. -                // Special test for 2-char characters. -                boolean foundFont = false; -                for (int f = 1 ; f < mFonts.size() ; f++) { -                    FontInfo fontInfo = mFonts.get(f); - -                    // need to check that the font can display the character. We test -                    // differently if the char is a high surrogate. -                    int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; -                    upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); -                    if (upTo == -1) { -                        total += fontInfo.mMetrics.charsWidth(text, i, charCount); -                        i += charCount; -                        foundFont = true; -                        break; - -                    } -                } - -                // in case no font can display the char, measure it with the main font. -                if (foundFont == false) { -                    int size = Character.isHighSurrogate(text[i]) ? 2 : 1; -                    total += mainFont.mMetrics.charsWidth(text, i, size); -                    i += size; -                } -            } -        } - -        return 0; -    } - -    /** -     * Return the width of the text. -     * -     * @param text  The text to measure -     * @param start The index of the first character to start measuring -     * @param end   1 beyond the index of the last character to measure -     * @return      The width of the text -     */ -    @Override -    public float measureText(String text, int start, int end) { -        return measureText(text.toCharArray(), start, end - start); -    } - -    /** -     * Return the width of the text. -     * -     * @param text  The text to measure -     * @return      The width of the text -     */ -    @Override -    public float measureText(String text) { -        return measureText(text.toCharArray(), 0, text.length()); -    } - -    /* -     * re-implement to call SpannableStringBuilder.measureText with a Paint object -     * instead of an _Original_Paint -     */ -    @Override -    public float measureText(CharSequence text, int start, int end) { -        if (text instanceof String) { -            return measureText((String)text, start, end); -        } -        if (text instanceof SpannedString || -            text instanceof SpannableString) { -            return measureText(text.toString(), start, end); -        } -        if (text instanceof SpannableStringBuilder) { -            return ((SpannableStringBuilder)text).measureText(start, end, this); -        } - -        char[] buf = TemporaryBuffer.obtain(end - start); -        TextUtils.getChars(text, start, end, buf, 0); -        float result = measureText(buf, 0, end - start); -        TemporaryBuffer.recycle(buf); -        return result; -    } - -    /** -     * Measure the text, stopping early if the measured width exceeds maxWidth. -     * Return the number of chars that were measured, and if measuredWidth is -     * not null, return in it the actual width measured. -     * -     * @param text  The text to measure -     * @param index The offset into text to begin measuring at -     * @param count The number of maximum number of entries to measure. If count -     *              is negative, then the characters before index are measured -     *              in reverse order. This allows for measuring the end of -     *              string. -     * @param maxWidth The maximum width to accumulate. -     * @param measuredWidth Optional. If not null, returns the actual width -     *                     measured. -     * @return The number of chars that were measured. Will always be <= -     *         abs(count). -     */ -    @Override -    public int breakText(char[] text, int index, int count, -                                float maxWidth, float[] measuredWidth) { -        int inc = count > 0 ? 1 : -1; - -        int measureIndex = 0; -        float measureAcc = 0; -        for (int i = index ; i != index + count ; i += inc, measureIndex++) { -            int start, end; -            if (i < index) { -                start = i; -                end = index; -            } else { -                start = index; -                end = i; -            } - -            // measure from start to end -            float res = measureText(text, start, end - start + 1); - -            if (measuredWidth != null) { -                measuredWidth[measureIndex] = res; -            } - -            measureAcc += res; -            if (res > maxWidth) { -                // we should not return this char index, but since it's 0-based and we need -                // to return a count, we simply return measureIndex; -                return measureIndex; -            } - -        } - -        return measureIndex; -    } - -    /** -     * Measure the text, stopping early if the measured width exceeds maxWidth. -     * Return the number of chars that were measured, and if measuredWidth is -     * not null, return in it the actual width measured. -     * -     * @param text  The text to measure -     * @param measureForwards If true, measure forwards, starting at index. -     *                        Otherwise, measure backwards, starting with the -     *                        last character in the string. -     * @param maxWidth The maximum width to accumulate. -     * @param measuredWidth Optional. If not null, returns the actual width -     *                     measured. -     * @return The number of chars that were measured. Will always be <= -     *         abs(count). -     */ -    @Override -    public int breakText(String text, boolean measureForwards, -                                float maxWidth, float[] measuredWidth) { -        return breakText(text, -                0 /* start */, text.length() /* end */, -                measureForwards, maxWidth, measuredWidth); -    } - -    /** -     * Measure the text, stopping early if the measured width exceeds maxWidth. -     * Return the number of chars that were measured, and if measuredWidth is -     * not null, return in it the actual width measured. -     * -     * @param text  The text to measure -     * @param start The offset into text to begin measuring at -     * @param end   The end of the text slice to measure. -     * @param measureForwards If true, measure forwards, starting at start. -     *                        Otherwise, measure backwards, starting with end. -     * @param maxWidth The maximum width to accumulate. -     * @param measuredWidth Optional. If not null, returns the actual width -     *                     measured. -     * @return The number of chars that were measured. Will always be <= -     *         abs(end - start). -     */ -    @Override -    public int breakText(CharSequence text, int start, int end, boolean measureForwards, -            float maxWidth, float[] measuredWidth) { -        char[] buf = new char[end - start]; -        int result; - -        TextUtils.getChars(text, start, end, buf, 0); - -        if (measureForwards) { -            result = breakText(buf, 0, end - start, maxWidth, measuredWidth); -        } else { -            result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth); -        } - -        return result; -    } - -    /** -     * Return the advance widths for the characters in the string. -     * -     * @param text     The text to measure -     * @param index    The index of the first char to to measure -     * @param count    The number of chars starting with index to measure -     * @param widths   array to receive the advance widths of the characters. -     *                 Must be at least a large as count. -     * @return         the actual number of widths returned. -     */ -    @Override -    public int getTextWidths(char[] text, int index, int count, -                             float[] widths) { -        if (mFonts.size() > 0) { -            if ((index | count) < 0 || index + count > text.length -                    || count > widths.length) { -                throw new ArrayIndexOutOfBoundsException(); -            } - -            // FIXME: handle multi-char characters. -            // Need to figure out if the lengths of the width array takes into account -            // multi-char characters. -            for (int i = 0; i < count; i++) { -                char c = text[i + index]; -                boolean found = false; -                for (FontInfo info : mFonts) { -                    if (info.mFont.canDisplay(c)) { -                        widths[i] = info.mMetrics.charWidth(c); -                        found = true; -                        break; -                    } -                } - -                if (found == false) { -                    // we stop there. -                    return i; -                } -            } - -            return count; -        } - -        return 0; -    } - -    /** -     * Return the advance widths for the characters in the string. -     * -     * @param text   The text to measure -     * @param start  The index of the first char to to measure -     * @param end    The end of the text slice to measure -     * @param widths array to receive the advance widths of the characters. -     *               Must be at least a large as the text. -     * @return       the number of unichars in the specified text. -     */ -    @Override -    public int getTextWidths(String text, int start, int end, float[] widths) { -        if ((start | end | (end - start) | (text.length() - end)) < 0) { -            throw new IndexOutOfBoundsException(); -        } -        if (end - start > widths.length) { -            throw new ArrayIndexOutOfBoundsException(); -        } - -        return getTextWidths(text.toCharArray(), start, end - start, widths); -    } - -    /* -     * re-implement to call SpannableStringBuilder.getTextWidths with a Paint object -     * instead of an _Original_Paint -     */ -    @Override -    public int getTextWidths(CharSequence text, int start, int end, float[] widths) { -        if (text instanceof String) { -            return getTextWidths((String)text, start, end, widths); -        } -        if (text instanceof SpannedString || text instanceof SpannableString) { -            return getTextWidths(text.toString(), start, end, widths); -        } -        if (text instanceof SpannableStringBuilder) { -            return ((SpannableStringBuilder)text).getTextWidths(start, end, widths, this); -        } - -        char[] buf = TemporaryBuffer.obtain(end - start); -        TextUtils.getChars(text, start, end, buf, 0); -        int result = getTextWidths(buf, 0, end - start, widths); -        TemporaryBuffer.recycle(buf); -        return result; -    } - -    @Override -    public int getTextWidths(String text, float[] widths) { -        return super.getTextWidths(text, widths); -    } - -    /** -     * Return the path (outline) for the specified text. -     * Note: just like Canvas.drawText, this will respect the Align setting in -     * the paint. -     * -     * @param text     The text to retrieve the path from -     * @param index    The index of the first character in text -     * @param count    The number of characterss starting with index -     * @param x        The x coordinate of the text's origin -     * @param y        The y coordinate of the text's origin -     * @param path     The path to receive the data describing the text. Must -     *                 be allocated by the caller. -     */ -    @Override -    public void getTextPath(char[] text, int index, int count, -                            float x, float y, Path path) { - -        // TODO this is the ORIGINAL implementation. REPLACE AS NEEDED OR REMOVE - -        if ((index | count) < 0 || index + count > text.length) { -            throw new ArrayIndexOutOfBoundsException(); -        } - -        // TODO native_getTextPath(mNativePaint, text, index, count, x, y, path.ni()); - -        throw new UnsupportedOperationException("IMPLEMENT AS NEEDED"); -    } - -    /** -     * Return the path (outline) for the specified text. -     * Note: just like Canvas.drawText, this will respect the Align setting -     * in the paint. -     * -     * @param text  The text to retrieve the path from -     * @param start The first character in the text -     * @param end   1 past the last charcter in the text -     * @param x     The x coordinate of the text's origin -     * @param y     The y coordinate of the text's origin -     * @param path  The path to receive the data describing the text. Must -     *              be allocated by the caller. -     */ -    @Override -    public void getTextPath(String text, int start, int end, -                            float x, float y, Path path) { -        if ((start | end | (end - start) | (text.length() - end)) < 0) { -            throw new IndexOutOfBoundsException(); -        } - -        getTextPath(text.toCharArray(), start, end - start, x, y, path); -    } - -    /** -     * Return in bounds (allocated by the caller) the smallest rectangle that -     * encloses all of the characters, with an implied origin at (0,0). -     * -     * @param text  String to measure and return its bounds -     * @param start Index of the first char in the string to measure -     * @param end   1 past the last char in the string measure -     * @param bounds Returns the unioned bounds of all the text. Must be -     *               allocated by the caller. -     */ -    @Override -    public void getTextBounds(String text, int start, int end, Rect bounds) { -        if ((start | end | (end - start) | (text.length() - end)) < 0) { -            throw new IndexOutOfBoundsException(); -        } -        if (bounds == null) { -            throw new NullPointerException("need bounds Rect"); -        } - -        getTextBounds(text.toCharArray(), start, end - start, bounds); -    } - -    /** -     * Return in bounds (allocated by the caller) the smallest rectangle that -     * encloses all of the characters, with an implied origin at (0,0). -     * -     * @param text  Array of chars to measure and return their unioned bounds -     * @param index Index of the first char in the array to measure -     * @param count The number of chars, beginning at index, to measure -     * @param bounds Returns the unioned bounds of all the text. Must be -     *               allocated by the caller. -     */ -    @Override -    public void getTextBounds(char[] text, int index, int count, Rect bounds) { -        // FIXME -        if (mFonts.size() > 0) { -            if ((index | count) < 0 || index + count > text.length) { -                throw new ArrayIndexOutOfBoundsException(); -            } -            if (bounds == null) { -                throw new NullPointerException("need bounds Rect"); -            } - -            FontInfo mainInfo = mFonts.get(0); - -            Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count, mFontContext); -            bounds.set(0, 0, (int)rect.getWidth(), (int)rect.getHeight()); -        } -    } - -    public static void finalizer(int foo) { -        // pass -    } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java new file mode 100644 index 000000000000..e8079edda22b --- /dev/null +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -0,0 +1,750 @@ +/* + * Copyright (C) 2010 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 android.graphics; + +import com.android.layoutlib.bridge.DelegateManager; + +import android.graphics.Paint.FontMetrics; +import android.graphics.Paint.FontMetricsInt; + +import java.awt.Font; +import java.awt.Toolkit; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Delegate implementing the native methods of android.graphics.Paint + * + * Through the layoutlib_create tool, the original native methods of Paint have been replaced + * by calls to methods of the same name in this delegate class. + * + * This class behaves like the original native implementation, but in Java, keeping previously + * native data into its own objects and mapping them to int that are sent back and forth between + * it and the original Paint class. + * + * @see DelegateManager + * + */ +public class Paint_Delegate { + +    /** +     * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}. +     */ +    public static final class FontInfo { +        Font mFont; +        java.awt.FontMetrics mMetrics; +    } + +    // ---- delegate manager ---- +    private static final DelegateManager<Paint_Delegate> sManager = +            new DelegateManager<Paint_Delegate>(); + +    // ---- delegate helper data ---- +    private List<FontInfo> mFonts; +    private final FontRenderContext mFontContext = new FontRenderContext( +            new AffineTransform(), true, true); + +    // ---- delegate data ---- +    private int mFlags; +    private int mColor; +    private int mStyle; +    private int mCap; +    private int mJoin; +    private int mAlign; +    private int mTypeface; +    private float mStrokeWidth; +    private float mStrokeMiter; +    private float mTextSize; +    private float mTextScaleX; +    private float mTextSkewX; + + +    // ---- Public Helper methods ---- + +    /** +     * Returns the list of {@link Font} objects. The first item is the main font, the rest +     * are fall backs for characters not present in the main font. +     */ +    public List<FontInfo> getFonts() { +        return mFonts; +    } + + +    // ---- native methods ---- + +    /*package*/ static int getFlags(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mFlags; +    } + +    /*package*/ static void setFlags(Paint thisPaint, int flags) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mFlags = flags; +    } + +    /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) { +        setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa); +    } + +    /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) { +        setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText); +    } + +    /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) { +        setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText); +    } + +    /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) { +        setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText); +    } + +    /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) { +        setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText); +    } + +    /*package*/ static void setDither(Paint thisPaint, boolean dither) { +        setFlag(thisPaint, Paint.DITHER_FLAG, dither); +    } + +    /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) { +        setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText); +    } + +    /*package*/ static int getColor(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mColor; +    } + +    /*package*/ static void setColor(Paint thisPaint, int color) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mColor = color; +    } + +    /*package*/ static int getAlpha(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mColor >>> 24; +    } + +    /*package*/ static void setAlpha(Paint thisPaint, int a) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mColor = (a << 24) | (delegate.mColor & 0x00FFFFFF); +    } + +    /*package*/ static float getStrokeWidth(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 1.f; +        } + +        return delegate.mStrokeWidth; +    } + +    /*package*/ static void setStrokeWidth(Paint thisPaint, float width) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mStrokeWidth = width; +    } + +    /*package*/ static float getStrokeMiter(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 1.f; +        } + +        return delegate.mStrokeMiter; +    } + +    /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mStrokeMiter = miter; +    } + +    /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy, +            int color) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static float getTextSize(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 1.f; +        } + +        return delegate.mTextSize; +    } + +    /*package*/ static void setTextSize(Paint thisPaint, float textSize) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mTextSize = textSize; +    } + +    /*package*/ static float getTextScaleX(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 1.f; +        } + +        return delegate.mTextScaleX; +    } + +    /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mTextScaleX = scaleX; +    } + +    /*package*/ static float getTextSkewX(Paint thisPaint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 1.f; +        } + +        return delegate.mTextSkewX; +    } + +    /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mTextSkewX = skewX; +    } + +    /*package*/ static float ascent(Paint thisPaint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static float descent(Paint thisPaint) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index, +            int count) { +        // WARNING: the logic in this method is similar to Canvas.drawText. +        // Any change to this method should be reflected in Canvas.drawText + +        // get the delegate +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        if (delegate.mFonts.size() > 0) { +            FontInfo mainFont = delegate.mFonts.get(0); +            int i = index; +            int lastIndex = index + count; +            float total = 0f; +            while (i < lastIndex) { +                // always start with the main font. +                int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); +                if (upTo == -1) { +                    // shortcut to exit +                    return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i); +                } else if (upTo > 0) { +                    total += mainFont.mMetrics.charsWidth(text, i, upTo - i); +                    i = upTo; +                    // don't call continue at this point. Since it is certain the main font +                    // cannot display the font a index upTo (now ==i), we move on to the +                    // fallback fonts directly. +                } + +                // no char supported, attempt to read the next char(s) with the +                // fallback font. In this case we only test the first character +                // and then go back to test with the main font. +                // Special test for 2-char characters. +                boolean foundFont = false; +                for (int f = 1 ; f < delegate.mFonts.size() ; f++) { +                    FontInfo fontInfo = delegate.mFonts.get(f); + +                    // need to check that the font can display the character. We test +                    // differently if the char is a high surrogate. +                    int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; +                    upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); +                    if (upTo == -1) { +                        total += fontInfo.mMetrics.charsWidth(text, i, charCount); +                        i += charCount; +                        foundFont = true; +                        break; + +                    } +                } + +                // in case no font can display the char, measure it with the main font. +                if (foundFont == false) { +                    int size = Character.isHighSurrogate(text[i]) ? 2 : 1; +                    total += mainFont.mMetrics.charsWidth(text, i, size); +                    i += size; +                } +            } +        } + +        return 0; +    } + +    /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end) { +        return native_measureText(thisPaint, text.toCharArray(), start, end - start); +    } + +    /*package*/ static float native_measureText(Paint thisPaint, String text) { +        return native_measureText(thisPaint, text.toCharArray(), 0, text.length()); +    } + +    /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count, +            float maxWidth, float[] measuredWidth) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards, +            float maxWidth, float[] measuredWidth) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + + +    /*package*/ static int native_init() { +        Paint_Delegate newDelegate = new Paint_Delegate(); +        return sManager.addDelegate(newDelegate); +    } + +    /*package*/ static int native_initWithPaint(int paint) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(paint); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        Paint_Delegate newDelegate = new Paint_Delegate(delegate); +        return sManager.addDelegate(newDelegate); +    } + +    /*package*/ static void native_reset(int native_object) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.reset(); +    } + +    /*package*/ static void native_set(int native_dst, int native_src) { +        // get the delegate from the native int. +        Paint_Delegate delegate_dst = sManager.getDelegate(native_dst); +        if (delegate_dst == null) { +            assert false; +            return; +        } + +        // get the delegate from the native int. +        Paint_Delegate delegate_src = sManager.getDelegate(native_src); +        if (delegate_src == null) { +            assert false; +            return; +        } + +        delegate_dst.set(delegate_src); +    } + +    /*package*/ static int native_getStyle(int native_object) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mStyle; +    } + +    /*package*/ static void native_setStyle(int native_object, int style) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mStyle = style; +    } + +    /*package*/ static int native_getStrokeCap(int native_object) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mCap; +    } + +    /*package*/ static void native_setStrokeCap(int native_object, int cap) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mCap = cap; +    } + +    /*package*/ static int native_getStrokeJoin(int native_object) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mJoin; +    } + +    /*package*/ static void native_setStrokeJoin(int native_object, int join) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mJoin = join; +    } + +    /*package*/ static boolean native_getFillPath(int native_object, int src, int dst) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_setShader(int native_object, int shader) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_setColorFilter(int native_object, int filter) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_setXfermode(int native_object, int xfermode) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_setPathEffect(int native_object, int effect) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_setMaskFilter(int native_object, int maskfilter) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_setTypeface(int native_object, int typeface) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mTypeface = typeface; +    } + +    /*package*/ static int native_setRasterizer(int native_object, int rasterizer) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + + +    /*package*/ static int native_getTextAlign(int native_object) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return 0; +        } + +        return delegate.mAlign; +    } + +    /*package*/ static void native_setTextAlign(int native_object, int align) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(native_object); +        if (delegate == null) { +            assert false; +            return; +        } + +        delegate.mAlign = align; +    } + +    /*package*/ static float native_getFontMetrics(int native_paint, FontMetrics metrics) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_getTextWidths(int native_object, char[] text, int index, +            int count, float[] widths) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_getTextWidths(int native_object, String text, int start, +            int end, float[] widths) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static float native_getTextRunAdvances(int native_object, +            char[] text, int index, int count, int contextIndex, int contextCount, +            int flags, float[] advances, int advancesIndex) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static float native_getTextRunAdvances(int native_object, +            String text, int start, int end, int contextStart, int contextEnd, +            int flags, float[] advances, int advancesIndex) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text, +            int contextStart, int contextLength, int flags, int offset, int cursorOpt) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, String text, +            int contextStart, int contextEnd, int flags, int offset, int cursorOpt) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_getTextPath(int native_object, int bidiFlags, +                char[] text, int index, int count, float x, float y, int path) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void native_getTextPath(int native_object, int bidiFlags, +            String text, int start, int end, float x, float y, int path) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start, +            int end, Rect bounds) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index, +            int count, Rect bounds) { +        // FIXME +        throw new UnsupportedOperationException(); +    } + +    /*package*/ static void finalizer(int nativePaint) { +        sManager.removeDelegate(nativePaint); +    } + +    // ---- Private delegate/helper methods ---- + +    private Paint_Delegate() { +        reset(); + +        mTypeface = Typeface.sDefaults[0].native_instance; +        updateFontObject(); +    } + +    private Paint_Delegate(Paint_Delegate paint) { +        set(paint); +        updateFontObject(); +    } + +    private void set(Paint_Delegate paint) { +        mFlags = paint.mFlags; +        mColor = paint.mColor; +        mStyle = paint.mStyle; +        mCap = paint.mCap; +        mJoin = paint.mJoin; +        mAlign = paint.mAlign; +        mTypeface = paint.mTypeface; +        mStrokeWidth = paint.mStrokeWidth; +        mStrokeMiter = paint.mStrokeMiter; +        mTextSize = paint.mTextSize; +        mTextScaleX = paint.mTextScaleX; +        mTextSkewX = paint.mTextSkewX; +    } + +    private void reset() { +        mFlags = Paint.DEFAULT_PAINT_FLAGS; +        mColor = 0; +        mStyle = 0; +        mCap = 0; +        mJoin = 0; +        mAlign = 0; +        mTypeface = 0; +        mStrokeWidth = 1.f; +        mStrokeMiter = 2.f; +        mTextSize = 20.f; +        mTextScaleX = 1.f; +        mTextSkewX = 0.f; +    } + +    /** +     * Update the {@link Font} object from the typeface, text size and scaling +     */ +    private void updateFontObject() { +        if (mTypeface != 0) { +            // Get the fonts from the TypeFace object. +            List<Font> fonts = Typeface_Delegate.getFonts(mTypeface); + +            // create new font objects as well as FontMetrics, based on the current text size +            // and skew info. +            ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size()); +            for (Font font : fonts) { +                FontInfo info = new FontInfo(); +                info.mFont = font.deriveFont(mTextSize); +                if (mTextScaleX != 1.0 || mTextSkewX != 0) { +                    // TODO: support skew +                    info.mFont = info.mFont.deriveFont(new AffineTransform( +                            mTextScaleX, mTextSkewX, 0, 0, 1, 0)); +                } +                info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont); + +                infoList.add(info); +            } + +            mFonts = Collections.unmodifiableList(infoList); +        } +    } + +    private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) { +        // get the delegate from the native int. +        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); +        if (delegate == null) { +            assert false; +            return; +        } + +        if (flagValue) { +            delegate.mFlags |= flagMask; +        } else { +            delegate.mFlags &= ~flagMask; +        } +    } +} diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java index 248bdab8ee0f..7e90e7d84a5d 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java @@ -72,7 +72,11 @@ public final class Typeface_Delegate {      }      public static List<Font> getFonts(Typeface typeface) { -        Typeface_Delegate delegate = sManager.getDelegate(typeface.native_instance); +        return getFonts(typeface.native_instance); +    } + +    public static List<Font> getFonts(int native_int) { +        Typeface_Delegate delegate = sManager.getDelegate(native_int);          if (delegate == null) {              assert false;              return null; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index 9eb83c8fa5e7..cdb41485447a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -24,6 +24,7 @@ import com.android.layoutlib.api.IProjectCallback;  import com.android.layoutlib.api.IResourceValue;  import com.android.layoutlib.api.IStyleResourceValue;  import com.android.layoutlib.api.IXmlPullParser; +import com.android.layoutlib.api.IDensityBasedResourceValue.Density;  import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;  import com.android.layoutlib.bridge.LayoutResult.LayoutViewInfo;  import com.android.ninepatch.NinePatch; @@ -33,7 +34,9 @@ import com.android.tools.layoutlib.create.OverrideMethod;  import android.content.ClipData;  import android.content.res.Configuration;  import android.graphics.Bitmap; +import android.graphics.Bitmap_Delegate;  import android.graphics.Canvas; +import android.graphics.Canvas_Delegate;  import android.graphics.Rect;  import android.graphics.Region;  import android.graphics.Typeface_Delegate; @@ -64,6 +67,7 @@ import android.widget.FrameLayout;  import android.widget.TabHost;  import android.widget.TabWidget; +import java.awt.image.BufferedImage;  import java.lang.ref.SoftReference;  import java.lang.reflect.Field;  import java.lang.reflect.Modifier; @@ -450,13 +454,28 @@ public final class Bridge implements ILayoutBridge {              view.layout(0, screenOffset, screenWidth, screenHeight);              // draw the views -            Canvas canvas = new Canvas(screenWidth, screenHeight - screenOffset, logger); +            // create the BufferedImage into which the layout will be rendered. +            BufferedImage image = new BufferedImage(screenWidth, screenHeight - screenOffset, +                    BufferedImage.TYPE_INT_ARGB); + +            // create an Android bitmap around the BufferedImage +            Bitmap bitmap = Bitmap_Delegate.createBitmap(image, Density.getEnum(density)); + +            // create a Canvas around the Android bitmap +            Canvas canvas = new Canvas(bitmap); + +            // to set the logger, get the native delegate +            Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas); +            canvasDelegate.setLogger(logger); +              root.draw(canvas); -            canvas.dispose(); +            canvasDelegate.dispose(); + +            return new LayoutResult( +                    visit(((ViewGroup)view).getChildAt(0), context), +                    image); -            return new LayoutResult(visit(((ViewGroup)view).getChildAt(0), context), -                    canvas.getImage());          } catch (PostInflateException e) {              return new LayoutResult(ILayoutResult.ERROR, "Error during post inflation process:\n"                      + e.getMessage()); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java index abbf2f0546c1..2c92567a44ab 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java @@ -19,6 +19,7 @@ package com.android.layoutlib.bridge;  import com.android.ninepatch.NinePatch;  import android.graphics.Canvas; +import android.graphics.Canvas_Delegate;  import android.graphics.ColorFilter;  import android.graphics.Rect;  import android.graphics.drawable.Drawable; @@ -80,7 +81,8 @@ public class NinePatchDrawable extends Drawable {      @Override      public void draw(Canvas canvas) {          Rect r = getBounds(); -        m9Patch.draw(canvas.getGraphics2d(), r.left, r.top, r.width(), r.height()); +        Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas); +        m9Patch.draw(canvasDelegate.getGraphics2d(), r.left, r.top, r.width(), r.height());          return;      } diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/AndroidGraphicsTests.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/AndroidGraphicsTests.java index 6e14e82e6902..ba3c51a6c6ac 100644 --- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/AndroidGraphicsTests.java +++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/AndroidGraphicsTests.java @@ -17,8 +17,6 @@  package com.android.layoutlib.bridge;  import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics._Original_Paint;  import android.text.TextPaint;  import junit.framework.TestCase; @@ -58,14 +56,6 @@ public class AndroidGraphicsTests extends TestCase {          }      } -    public void testPaint() { -        _Original_Paint o = new _Original_Paint(); -        assertNotNull(o); - -        Paint p = new Paint(); -        assertNotNull(p); -    } -      public void textTextPaint() {          TextPaint p = new TextPaint();          assertNotNull(p); diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java index 7c1eecdfc566..a86b5c91bb02 100644 --- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java +++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java @@ -87,7 +87,11 @@ public class TestNativeDelegate extends TestCase {              try {                  // try to load the method with the given parameter types. -                delegateClass.getDeclaredMethod(originalMethod.getName(), parameters); +                Method delegateMethod = delegateClass.getDeclaredMethod(originalMethod.getName(), +                        parameters); + +                // check that the method is static +                assertTrue((delegateMethod.getModifiers() & Modifier.STATIC) == Modifier.STATIC);              } catch (NoSuchMethodException e) {                  // compute a full class name that's long but not too long.                  StringBuilder sb = new StringBuilder(originalMethod.getName() + "("); diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index 0ecb4740f16d..c845cc4265e2 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -104,7 +104,9 @@ public final class CreateInfo implements ICreateInfo {       */      private final static String[] DELEGATE_CLASS_NATIVES = new String[] {          "android.graphics.Bitmap", +        "android.graphics.Canvas",          "android.graphics.Matrix", +        "android.graphics.Paint",          "android.graphics.Typeface",      }; @@ -126,11 +128,9 @@ public final class CreateInfo implements ICreateInfo {          new String[] {              "android.graphics.BitmapFactory",       "android.graphics._Original_BitmapFactory",              "android.graphics.BitmapShader",        "android.graphics._Original_BitmapShader", -            "android.graphics.Canvas",              "android.graphics._Original_Canvas",              "android.graphics.ComposeShader",       "android.graphics._Original_ComposeShader",              "android.graphics.DashPathEffect",       "android.graphics._Original_DashPathEffect",              "android.graphics.LinearGradient",      "android.graphics._Original_LinearGradient", -            "android.graphics.Paint",               "android.graphics._Original_Paint",              "android.graphics.Path",                "android.graphics._Original_Path",              "android.graphics.PorterDuffXfermode",  "android.graphics._Original_PorterDuffXfermode",              "android.graphics.RadialGradient",      "android.graphics._Original_RadialGradient", @@ -150,13 +150,6 @@ public final class CreateInfo implements ICreateInfo {       */      private final static String[] DELETE_RETURNS =          new String[] { -            "android.graphics.Paint",       // class to delete methods from -            "android.graphics.Paint$Align", // list of type identifying methods to delete -            "android.graphics.Paint$Style", -            "android.graphics.Paint$Join", -            "android.graphics.Paint$Cap", -            "android.graphics.Paint$FontMetrics", -            "android.graphics.Paint$FontMetricsInt",              null };                         // separator, for next class/methods list.  } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java index 21d6682de5ea..c7968a4eb0e0 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java @@ -169,7 +169,7 @@ class DelegateMethodAdapter implements MethodVisitor {          // Construct the descriptor of the delegate. For a static method, it's the same          // however for an instance method we need to pass the 'this' reference first          String desc = mDesc; -        if (!mIsStatic && argTypes.length > 0) { +        if (!mIsStatic) {              Type[] argTypes2 = new Type[argTypes.length + 1];              argTypes2[0] = Type.getObjectType(mClassName); |