diff options
151 files changed, 3474 insertions, 618 deletions
diff --git a/api/current.xml b/api/current.xml index 3535ffc..eead0f5 100644 --- a/api/current.xml +++ b/api/current.xml @@ -10657,6 +10657,17 @@ visibility="public" > </field> +<field name="windowActionBarSize" + type="int" + transient="false" + volatile="false" + value="16843563" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="windowActionBarStyle" type="int" transient="false" @@ -21946,6 +21957,17 @@ visibility="public" > </method> +<method name="getFragmentManager" + return="android.app.FragmentManager" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getInstanceCount" return="long" abstract="false" @@ -27377,18 +27399,6 @@ visibility="public" > </constructor> -<constructor name="DialogFragment" - type="android.app.DialogFragment" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="style" type="int"> -</parameter> -<parameter name="theme" type="int"> -</parameter> -</constructor> <method name="dismiss" return="void" abstract="false" @@ -27485,6 +27495,21 @@ <parameter name="cancelable" type="boolean"> </parameter> </method> +<method name="setStyle" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="style" type="int"> +</parameter> +<parameter name="theme" type="int"> +</parameter> +</method> <method name="show" return="void" abstract="false" @@ -27765,6 +27790,28 @@ visibility="public" > </method> +<method name="getArguments" + return="android.os.Bundle" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getFragmentManager" + return="android.app.FragmentManager" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getId" return="int" abstract="false" @@ -27845,18 +27892,23 @@ </parameter> <parameter name="fname" type="java.lang.String"> </parameter> -<exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException"> -</exception> -<exception name="IllegalAccessException" type="java.lang.IllegalAccessException"> -</exception> -<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException"> -</exception> -<exception name="InstantiationException" type="java.lang.InstantiationException"> -</exception> -<exception name="InvocationTargetException" type="java.lang.reflect.InvocationTargetException"> -</exception> -<exception name="NoSuchMethodException" type="java.lang.NoSuchMethodException"> -</exception> +</method> +<method name="instantiate" + return="android.app.Fragment" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="fname" type="java.lang.String"> +</parameter> +<parameter name="args" type="android.os.Bundle"> +</parameter> </method> <method name="isAdded" return="boolean" @@ -28233,6 +28285,19 @@ <parameter name="view" type="android.view.View"> </parameter> </method> +<method name="setArguments" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="args" type="android.os.Bundle"> +</parameter> +</method> <method name="setHasOptionsMenu" return="void" abstract="false" @@ -28301,6 +28366,156 @@ </parameter> </method> </class> +<class name="Fragment.InstantiationException" + extends="android.util.AndroidRuntimeException" + abstract="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="Fragment.InstantiationException" + type="android.app.Fragment.InstantiationException" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="msg" type="java.lang.String"> +</parameter> +<parameter name="cause" type="java.lang.Exception"> +</parameter> +</constructor> +</class> +<interface name="FragmentManager" + abstract="true" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="findFragmentById" + return="android.app.Fragment" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="id" type="int"> +</parameter> +</method> +<method name="findFragmentByTag" + return="android.app.Fragment" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="tag" type="java.lang.String"> +</parameter> +</method> +<method name="getFragment" + return="android.app.Fragment" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="bundle" type="android.os.Bundle"> +</parameter> +<parameter name="key" type="java.lang.String"> +</parameter> +</method> +<method name="openTransaction" + return="android.app.FragmentTransaction" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="popBackStack" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="popBackStack" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="name" type="java.lang.String"> +</parameter> +<parameter name="flags" type="int"> +</parameter> +</method> +<method name="popBackStack" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="id" type="int"> +</parameter> +<parameter name="flags" type="int"> +</parameter> +</method> +<method name="putFragment" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="bundle" type="android.os.Bundle"> +</parameter> +<parameter name="key" type="java.lang.String"> +</parameter> +<parameter name="fragment" type="android.app.Fragment"> +</parameter> +</method> +<field name="POP_BACK_STACK_INCLUSIVE" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</interface> <interface name="FragmentTransaction" abstract="true" static="false" @@ -138394,6 +138609,17 @@ visibility="public" > </method> +<method name="invalidateHeaders" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="loadHeadersFromResource" return="void" abstract="false" @@ -138422,8 +138648,8 @@ <parameter name="target" type="java.util.List<android.preference.PreferenceActivity.Header>"> </parameter> </method> -<method name="onGetInitialFragment" - return="java.lang.String" +<method name="onGetInitialHeader" + return="android.preference.PreferenceActivity.Header" abstract="false" native="false" synchronized="false" @@ -138525,6 +138751,8 @@ > <parameter name="fragmentName" type="java.lang.String"> </parameter> +<parameter name="args" type="android.os.Bundle"> +</parameter> </method> <method name="switchToHeader" return="void" @@ -138538,7 +138766,42 @@ > <parameter name="fragmentName" type="java.lang.String"> </parameter> +<parameter name="args" type="android.os.Bundle"> +</parameter> </method> +<field name="EXTRA_NO_HEADERS" + type="java.lang.String" + transient="false" + volatile="false" + value="":android:no_headers"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="EXTRA_SHOW_FRAGMENT" + type="java.lang.String" + transient="false" + volatile="false" + value="":android:show_fragment"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="EXTRA_SHOW_FRAGMENT_ARGUMENTS" + type="java.lang.String" + transient="false" + volatile="false" + value="":android:show_fragment_args"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> </class> <class name="PreferenceActivity.Header" extends="java.lang.Object" @@ -179173,6 +179436,18 @@ deprecated="not deprecated" visibility="public" > +<parameter name="name" type="java.lang.String"> +</parameter> +<parameter name="cause" type="java.lang.Throwable"> +</parameter> +</constructor> +<constructor name="AndroidException" + type="android.util.AndroidException" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> <parameter name="cause" type="java.lang.Exception"> </parameter> </constructor> @@ -179210,6 +179485,18 @@ deprecated="not deprecated" visibility="public" > +<parameter name="name" type="java.lang.String"> +</parameter> +<parameter name="cause" type="java.lang.Throwable"> +</parameter> +</constructor> +<constructor name="AndroidRuntimeException" + type="android.util.AndroidRuntimeException" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> <parameter name="cause" type="java.lang.Exception"> </parameter> </constructor> diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d7bab1b..ec3cbc3 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -667,7 +667,7 @@ public class Activity extends ContextThemeWrapper private CharSequence mTitle; private int mTitleColor = 0; - final FragmentManager mFragments = new FragmentManager(); + final FragmentManagerImpl mFragments = new FragmentManagerImpl(); SparseArray<LoaderManagerImpl> mAllLoaderManagers; LoaderManagerImpl mLoaderManager; @@ -1580,11 +1580,19 @@ public class Activity extends ContextThemeWrapper } /** + * Return the FragmentManager for interacting with fragments associated + * with this activity. + */ + public FragmentManager getFragmentManager() { + return mFragments; + } + + /** * Start a series of edit operations on the Fragments associated with * this activity. */ public FragmentTransaction openFragmentTransaction() { - return new BackStackEntry(mFragments); + return mFragments.openTransaction(); } void invalidateFragmentIndex(int index) { @@ -2072,7 +2080,7 @@ public class Activity extends ContextThemeWrapper * to pop, else false. */ public boolean popBackStack() { - return popBackStack(null, 0); + return mFragments.popBackStack(); } /** @@ -2085,7 +2093,7 @@ public class Activity extends ContextThemeWrapper * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. */ public boolean popBackStack(String name, int flags) { - return mFragments.popBackStackState(mHandler, name, flags); + return mFragments.popBackStack(name, flags); } /** @@ -2099,7 +2107,7 @@ public class Activity extends ContextThemeWrapper * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. */ public boolean popBackStack(int id, int flags) { - return mFragments.popBackStackState(mHandler, id, flags); + return mFragments.popBackStack(id, flags); } /** @@ -3999,43 +4007,36 @@ public class Activity extends ContextThemeWrapper + ": Must specify unique android:id for " + fname); } - try { - // If we restored from a previous state, we may already have - // instantiated this fragment from the state and should use - // that instance instead of making a new one. - Fragment fragment = mFragments.findFragmentById(id); - if (FragmentManager.DEBUG) Log.v(TAG, "onCreateView: id=0x" - + Integer.toHexString(id) + " fname=" + fname - + " existing=" + fragment); - if (fragment == null) { - fragment = Fragment.instantiate(this, fname); - fragment.mFromLayout = true; - fragment.mFragmentId = id; - fragment.mTag = tag; - fragment.mImmediateActivity = this; - mFragments.addFragment(fragment, true); - } - // If this fragment is newly instantiated (either right now, or - // from last saved state), then give it the attributes to - // initialize itself. - if (!fragment.mRetaining) { - fragment.onInflate(this, attrs, fragment.mSavedFragmentState); - } - if (fragment.mView == null) { - throw new IllegalStateException("Fragment " + fname - + " did not create a view."); - } - fragment.mView.setId(id); - if (fragment.mView.getTag() == null) { - fragment.mView.setTag(tag); - } - return fragment.mView; - } catch (Exception e) { - InflateException ie = new InflateException(attrs.getPositionDescription() - + ": Error inflating fragment " + fname); - ie.initCause(e); - throw ie; + // If we restored from a previous state, we may already have + // instantiated this fragment from the state and should use + // that instance instead of making a new one. + Fragment fragment = mFragments.findFragmentById(id); + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x" + + Integer.toHexString(id) + " fname=" + fname + + " existing=" + fragment); + if (fragment == null) { + fragment = Fragment.instantiate(this, fname); + fragment.mFromLayout = true; + fragment.mFragmentId = id; + fragment.mTag = tag; + fragment.mImmediateActivity = this; + mFragments.addFragment(fragment, true); + } + // If this fragment is newly instantiated (either right now, or + // from last saved state), then give it the attributes to + // initialize itself. + if (!fragment.mRetaining) { + fragment.onInflate(this, attrs, fragment.mSavedFragmentState); + } + if (fragment.mView == null) { + throw new IllegalStateException("Fragment " + fname + + " did not create a view."); + } + fragment.mView.setId(id); + if (fragment.mView.getTag() == null) { + fragment.mView.setTag(tag); } + return fragment.mView; } /** diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackEntry.java index d63b862..520e4fd 100644 --- a/core/java/android/app/BackStackEntry.java +++ b/core/java/android/app/BackStackEntry.java @@ -29,7 +29,7 @@ final class BackStackState implements Parcelable { final String mName; final int mIndex; - public BackStackState(FragmentManager fm, BackStackEntry bse) { + public BackStackState(FragmentManagerImpl fm, BackStackEntry bse) { int numRemoved = 0; BackStackEntry.Op op = bse.mHead; while (op != null) { @@ -38,6 +38,10 @@ final class BackStackState implements Parcelable { } mOps = new int[bse.mNumOp*5 + numRemoved]; + if (!bse.mAddToBackStack) { + throw new IllegalStateException("Not on back stack"); + } + op = bse.mHead; int pos = 0; while (op != null) { @@ -70,14 +74,15 @@ final class BackStackState implements Parcelable { mIndex = in.readInt(); } - public BackStackEntry instantiate(FragmentManager fm) { + public BackStackEntry instantiate(FragmentManagerImpl fm) { BackStackEntry bse = new BackStackEntry(fm); int pos = 0; while (pos < mOps.length) { BackStackEntry.Op op = new BackStackEntry.Op(); op.cmd = mOps[pos++]; + if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, + "BSE " + bse + " set base fragment #" + mOps[pos]); Fragment f = fm.mActive.get(mOps[pos++]); - f.mBackStackNesting++; op.fragment = f; op.enterAnim = mOps[pos++]; op.exitAnim = mOps[pos++]; @@ -85,7 +90,10 @@ final class BackStackState implements Parcelable { if (N > 0) { op.removed = new ArrayList<Fragment>(N); for (int i=0; i<N; i++) { - op.removed.add(fm.mActive.get(mOps[pos++])); + if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, + "BSE " + bse + " set remove fragment #" + mOps[pos]); + Fragment r = fm.mActive.get(mOps[pos++]); + op.removed.add(r); } } bse.addOp(op); @@ -94,6 +102,8 @@ final class BackStackState implements Parcelable { bse.mTransitionStyle = mTransitionStyle; bse.mName = mName; bse.mIndex = mIndex; + bse.mAddToBackStack = true; + bse.bumpBackStackNesting(1); return bse; } @@ -127,7 +137,7 @@ final class BackStackState implements Parcelable { final class BackStackEntry implements FragmentTransaction, Runnable { static final String TAG = "BackStackEntry"; - final FragmentManager mManager; + final FragmentManagerImpl mManager; static final int OP_NULL = 0; static final int OP_ADD = 1; @@ -158,7 +168,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { boolean mCommitted; int mIndex; - public BackStackEntry(FragmentManager manager) { + public BackStackEntry(FragmentManagerImpl manager) { mManager = manager; } @@ -295,9 +305,32 @@ final class BackStackEntry implements FragmentTransaction, Runnable { return this; } + void bumpBackStackNesting(int amt) { + if (!mAddToBackStack) { + return; + } + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting in " + this + + " by " + amt); + Op op = mHead; + while (op != null) { + op.fragment.mBackStackNesting += amt; + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " + + op.fragment + " to " + op.fragment.mBackStackNesting); + if (op.removed != null) { + for (int i=op.removed.size()-1; i>=0; i--) { + Fragment r = op.removed.get(i); + r.mBackStackNesting += amt; + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " + + r + " to " + r.mBackStackNesting); + } + } + op = op.next; + } + } + public int commit() { if (mCommitted) throw new IllegalStateException("commit already called"); - if (FragmentManager.DEBUG) Log.v(TAG, "Commit: " + this); + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this); mCommitted = true; if (mAddToBackStack) { mIndex = mManager.allocBackStackIndex(this); @@ -309,7 +342,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } public void run() { - if (FragmentManager.DEBUG) Log.v(TAG, "Run: " + this); + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this); if (mAddToBackStack) { if (mIndex < 0) { @@ -317,14 +350,13 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } } + bumpBackStackNesting(1); + Op op = mHead; while (op != null) { switch (op.cmd) { case OP_ADD: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting++; - } f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } break; @@ -333,48 +365,38 @@ final class BackStackEntry implements FragmentTransaction, Runnable { if (mManager.mAdded != null) { for (int i=0; i<mManager.mAdded.size(); i++) { Fragment old = mManager.mAdded.get(i); - if (FragmentManager.DEBUG) Log.v(TAG, + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "OP_REPLACE: adding=" + f + " old=" + old); if (old.mContainerId == f.mContainerId) { if (op.removed == null) { op.removed = new ArrayList<Fragment>(); } op.removed.add(old); + old.mNextAnim = op.exitAnim; if (mAddToBackStack) { - old.mBackStackNesting++; + old.mBackStackNesting += 1; + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " + + old + " to " + old.mBackStackNesting); } - old.mNextAnim = op.exitAnim; mManager.removeFragment(old, mTransition, mTransitionStyle); } } } - if (mAddToBackStack) { - f.mBackStackNesting++; - } f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } break; case OP_REMOVE: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting++; - } f.mNextAnim = op.exitAnim; mManager.removeFragment(f, mTransition, mTransitionStyle); } break; case OP_HIDE: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting++; - } f.mNextAnim = op.exitAnim; mManager.hideFragment(f, mTransition, mTransitionStyle); } break; case OP_SHOW: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting++; - } f.mNextAnim = op.enterAnim; mManager.showFragment(f, mTransition, mTransitionStyle); } break; @@ -399,36 +421,29 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } public void popFromBackStack() { - if (FragmentManager.DEBUG) Log.v(TAG, "popFromBackStack: " + this); + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this); + + bumpBackStackNesting(-1); Op op = mTail; while (op != null) { switch (op.cmd) { case OP_ADD: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting--; - } f.mImmediateActivity = null; mManager.removeFragment(f, - FragmentManager.reverseTransit(mTransition), + FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; case OP_REPLACE: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting--; - } f.mImmediateActivity = null; mManager.removeFragment(f, - FragmentManager.reverseTransit(mTransition), + FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); if (op.removed != null) { for (int i=0; i<op.removed.size(); i++) { Fragment old = op.removed.get(i); - if (mAddToBackStack) { - old.mBackStackNesting--; - } f.mImmediateActivity = mManager.mActivity; mManager.addFragment(old, false); } @@ -436,27 +451,18 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } break; case OP_REMOVE: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting--; - } f.mImmediateActivity = mManager.mActivity; mManager.addFragment(f, false); } break; case OP_HIDE: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting--; - } mManager.showFragment(f, - FragmentManager.reverseTransit(mTransition), mTransitionStyle); + FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; case OP_SHOW: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting--; - } mManager.hideFragment(f, - FragmentManager.reverseTransit(mTransition), mTransitionStyle); + FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); } break; default: { throw new IllegalArgumentException("Unknown cmd: " + op.cmd); @@ -467,7 +473,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } mManager.moveToState(mManager.mCurState, - FragmentManager.reverseTransit(mTransition), mTransitionStyle, true); + FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true); if (mManager.mNeedMenuInvalidate && mManager.mActivity != null) { mManager.mActivity.invalidateOptionsMenu(); mManager.mNeedMenuInvalidate = false; diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java index 391f672..3124f0d 100644 --- a/core/java/android/app/DialogFragment.java +++ b/core/java/android/app/DialogFragment.java @@ -41,26 +41,26 @@ public class DialogFragment extends Fragment implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { /** - * Style for {@link #DialogFragment(int, int)} constructor: a basic, + * Style for {@link #setStyle(int, int)}: a basic, * normal dialog. */ public static final int STYLE_NORMAL = 0; /** - * Style for {@link #DialogFragment(int, int)} constructor: don't include + * Style for {@link #setStyle(int, int)}: don't include * a title area. */ public static final int STYLE_NO_TITLE = 1; /** - * Style for {@link #DialogFragment(int, int)} constructor: don't draw + * Style for {@link #setStyle(int, int)}: don't draw * any frame at all; the view hierarchy returned by {@link #onCreateView} * is entirely responsible for drawing the dialog. */ public static final int STYLE_NO_FRAME = 2; /** - * Style for {@link #DialogFragment(int, int)} constructor: like + * Style for {@link #setStyle(int, int)}: like * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog. * The user can not touch it, and its window will not receive input focus. */ @@ -84,11 +84,12 @@ public class DialogFragment extends Fragment } /** - * Constructor to customize the basic appearance and behavior of the + * Call to customize the basic appearance and behavior of the * fragment's dialog. This can be used for some common dialog behaviors, * taking care of selecting flags, theme, and other options for you. The * same effect can be achieve by manually setting Dialog and Window - * attributes yourself. + * attributes yourself. Calling this after the fragment's Dialog is + * created will have no effect. * * @param style Selects a standard style: may be {@link #STYLE_NORMAL}, * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or @@ -96,7 +97,7 @@ public class DialogFragment extends Fragment * @param theme Optional custom theme. If 0, an appropriate theme (based * on the style) will be selected for you. */ - public DialogFragment(int style, int theme) { + public void setStyle(int style, int theme) { mStyle = style; if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { mTheme = android.R.style.Theme_Dialog_NoFrame; diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 2f61345..bc839d7 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -24,6 +24,7 @@ import android.content.res.Configuration; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.util.AndroidRuntimeException; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; @@ -38,7 +39,6 @@ import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; import android.widget.AdapterView; -import java.lang.reflect.InvocationTargetException; import java.util.HashMap; final class FragmentState implements Parcelable { @@ -51,6 +51,7 @@ final class FragmentState implements Parcelable { final int mContainerId; final String mTag; final boolean mRetainInstance; + final Bundle mArguments; Bundle mSavedFragmentState; @@ -64,6 +65,7 @@ final class FragmentState implements Parcelable { mContainerId = frag.mContainerId; mTag = frag.mTag; mRetainInstance = frag.mRetainInstance; + mArguments = frag.mArguments; } public FragmentState(Parcel in) { @@ -74,6 +76,7 @@ final class FragmentState implements Parcelable { mContainerId = in.readInt(); mTag = in.readString(); mRetainInstance = in.readInt() != 0; + mArguments = in.readBundle(); mSavedFragmentState = in.readBundle(); } @@ -82,11 +85,7 @@ final class FragmentState implements Parcelable { return mInstance; } - try { - mInstance = Fragment.instantiate(activity, mClassName); - } catch (Exception e) { - throw new RuntimeException("Unable to restore fragment " + mClassName, e); - } + mInstance = Fragment.instantiate(activity, mClassName, mArguments); if (mSavedFragmentState != null) { mSavedFragmentState.setClassLoader(activity.getClassLoader()); @@ -116,6 +115,7 @@ final class FragmentState implements Parcelable { dest.writeInt(mContainerId); dest.writeString(mTag); dest.writeInt(mRetainInstance ? 1 : 0); + dest.writeBundle(mArguments); dest.writeBundle(mSavedFragmentState); } @@ -157,6 +157,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener // Internal unique name for this fragment; String mWho; + // Construction arguments; + Bundle mArguments; + // True if the fragment is in the list of added fragments. boolean mAdded; @@ -220,46 +223,81 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener boolean mCheckedForLoaderManager; /** + * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when + * there is an instantiation failure. + */ + static public class InstantiationException extends AndroidRuntimeException { + public InstantiationException(String msg, Exception cause) { + super(msg, cause); + } + } + + /** * Default constructor. <strong>Every</string> fragment must have an * empty constructor, so it can be instantiated when restoring its * activity's state. It is strongly recommended that subclasses do not * have other constructors with parameters, since these constructors * will not be called when the fragment is re-instantiated; instead, + * arguments can be supplied by the caller with {@link #setArguments} + * and later retrieved by the Fragment with {@link #getArguments}. + * + * <p>The first place where application code should generally run is in + * {@link #onAttach(Activity)}, which is the point where the fragment is + * actually attached to its activity and thus capable of doing most * retrieve such parameters from the activity in {@link #onAttach(Activity)}. */ public Fragment() { } /** + * Like {@link #instantiate(Context, String, Bundle)} but with a null + * argument Bundle. + */ + public static Fragment instantiate(Context context, String fname) { + return instantiate(context, fname, null); + } + + /** * Create a new instance of a Fragment with the given class name. This is * the same as calling its empty constructor. * * @param context The calling context being used to instantiate the fragment. * This is currently just used to get its ClassLoader. * @param fname The class name of the fragment to instantiate. + * @param args Bundle of arguments to supply to the fragment, which it + * can retrieve with {@link #getArguments()}. May be null. * @return Returns a new fragment instance. - * @throws NoSuchMethodException The fragment does not have an empty constructor. - * @throws ClassNotFoundException The fragment class does not exist. - * @throws IllegalArgumentException Bad arguments supplied to fragment class - * constructor (should not happen). - * @throws InstantiationException Caller does not have permission to instantiate - * the fragment (for example its constructor is not public). - * @throws IllegalAccessException Caller does not have permission to access - * the given fragment class. - * @throws InvocationTargetException Failure running the fragment's constructor. - */ - public static Fragment instantiate(Context context, String fname) - throws NoSuchMethodException, ClassNotFoundException, - IllegalArgumentException, InstantiationException, - IllegalAccessException, InvocationTargetException { - Class<?> clazz = sClassMap.get(fname); - - if (clazz == null) { - // Class not found in the cache, see if it's real, and try to add it - clazz = context.getClassLoader().loadClass(fname); - sClassMap.put(fname, clazz); + * @throws InstantiationException If there is a failure in instantiating + * the given fragment class. This is a runtime exception; it is not + * normally expected to happen. + */ + public static Fragment instantiate(Context context, String fname, Bundle args) { + try { + Class<?> clazz = sClassMap.get(fname); + if (clazz == null) { + // Class not found in the cache, see if it's real, and try to add it + clazz = context.getClassLoader().loadClass(fname); + sClassMap.put(fname, clazz); + } + Fragment f = (Fragment)clazz.newInstance(); + if (args != null) { + args.setClassLoader(f.getClass().getClassLoader()); + f.mArguments = args; + } + return f; + } catch (ClassNotFoundException e) { + throw new InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } catch (java.lang.InstantiationException e) { + throw new InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } catch (IllegalAccessException e) { + throw new InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); } - return (Fragment)clazz.newInstance(); } void restoreViewState() { @@ -331,6 +369,28 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener } /** + * Supply the construction arguments for this fragment. This can only + * be called before the fragment has been attached to its activity; that + * is, you should call it immediately after constructing the fragment. The + * arguments supplied here will be retained across fragment destroy and + * creation. + */ + final public void setArguments(Bundle args) { + if (mIndex >= 0) { + throw new IllegalStateException("Fragment already active"); + } + mArguments = args; + } + + /** + * Return the arguments supplied when the fragment was instantiated, + * if any. + */ + final public Bundle getArguments() { + return mArguments; + } + + /** * Return the Activity this fragment is currently associated with. */ final public Activity getActivity() { @@ -338,6 +398,14 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener } /** + * Return the FragmentManager for interacting with fragments associated + * with this fragment's activity. + */ + final public FragmentManager getFragmentManager() { + return mActivity.mFragments; + } + + /** * Return true if the fragment is currently added to its activity. */ final public boolean isAdded() { diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 54e37b0..0556f05 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -35,6 +35,100 @@ import android.view.animation.AnimationUtils; import java.util.ArrayList; +/** + * Interface for interacting with {@link Fragment} objects inside of an + * {@link Activity} + */ +public interface FragmentManager { + /** + * Start a series of edit operations on the Fragments associated with + * this FragmentManager. + */ + public FragmentTransaction openTransaction(); + + /** + * Finds a fragment that was identified by the given id either when inflated + * from XML or as the container ID when added in a transaction. This first + * searches through fragments that are currently added to the manager's + * activity; if no such fragment is found, then all fragments currently + * on the back stack associated with this ID are searched. + * @return The fragment if found or null otherwise. + */ + public Fragment findFragmentById(int id); + + /** + * Finds a fragment that was identified by the given tag either when inflated + * from XML or as supplied when added in a transaction. This first + * searches through fragments that are currently added to the manager's + * activity; if no such fragment is found, then all fragments currently + * on the back stack are searched. + * @return The fragment if found or null otherwise. + */ + public Fragment findFragmentByTag(String tag); + + /** + * Flag for {@link #popBackStack(String, int)} + * and {@link #popBackStack(int, int)}: If set, and the name or ID of + * a back stack entry has been supplied, then all matching entries will + * be consumed until one that doesn't match is found or the bottom of + * the stack is reached. Otherwise, all entries up to but not including that entry + * will be removed. + */ + public static final int POP_BACK_STACK_INCLUSIVE = 1<<0; + + /** + * Pop the top state off the back stack. Returns true if there was one + * to pop, else false. + */ + public boolean popBackStack(); + + /** + * Pop the last fragment transition from the manager's fragment + * back stack. If there is nothing to pop, false is returned. + * @param name If non-null, this is the name of a previous back state + * to look for; if found, all states up to that state will be popped. The + * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether + * the named state itself is popped. If null, only the top state is popped. + * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. + */ + public boolean popBackStack(String name, int flags); + + /** + * Pop all back stack states up to the one with the given identifier. + * @param id Identifier of the stated to be popped. If no identifier exists, + * false is returned. + * The identifier is the number returned by + * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. The + * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether + * the named state itself is popped. + * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. + */ + public boolean popBackStack(int id, int flags); + + /** + * Put a reference to a fragment in a Bundle. This Bundle can be + * persisted as saved state, and when later restoring + * {@link #getFragment(Bundle, String)} will return the current + * instance of the same fragment. + * + * @param bundle The bundle in which to put the fragment reference. + * @param key The name of the entry in the bundle. + * @param fragment The Fragment whose reference is to be stored. + */ + public void putFragment(Bundle bundle, String key, Fragment fragment); + + /** + * Retrieve the current Fragment instance for a reference previously + * placed with {@link #putFragment(Bundle, String, Fragment)}. + * + * @param bundle The bundle from which to retrieve the fragment reference. + * @param key The name of the entry in the bundle. + * @return Returns the current Fragment instance that is associated with + * the given reference. + */ + public Fragment getFragment(Bundle bundle, String key); +} + final class FragmentManagerState implements Parcelable { FragmentState[] mActive; int[] mAdded; @@ -75,7 +169,7 @@ final class FragmentManagerState implements Parcelable { * @hide * Container for fragments associated with an activity. */ -public class FragmentManager { +class FragmentManagerImpl implements FragmentManager { static final boolean DEBUG = true; static final String TAG = "FragmentManager"; @@ -108,6 +202,47 @@ public class FragmentManager { } }; + public FragmentTransaction openTransaction() { + return new BackStackEntry(this); + } + + public boolean popBackStack() { + return popBackStackState(mActivity.mHandler, null, -1, 0); + } + + public boolean popBackStack(String name, int flags) { + return popBackStackState(mActivity.mHandler, name, -1, flags); + } + + public boolean popBackStack(int id, int flags) { + if (id < 0) { + throw new IllegalArgumentException("Bad id: " + id); + } + return popBackStackState(mActivity.mHandler, null, id, flags); + } + + public void putFragment(Bundle bundle, String key, Fragment fragment) { + if (fragment.mIndex < 0) { + throw new IllegalStateException("Fragment " + fragment + + " is not currently in the FragmentManager"); + } + bundle.putInt(key, fragment.mIndex); + } + + public Fragment getFragment(Bundle bundle, String key) { + int index = bundle.getInt(key); + if (index >= mActive.size()) { + throw new IllegalStateException("Fragement no longer exists for key " + + key + ": index " + index); + } + Fragment f = mActive.get(index); + if (f == null) { + throw new IllegalStateException("Fragement no longer exists for key " + + key + ": index " + index); + } + return f; + } + Animatable loadAnimatable(Fragment fragment, int transit, boolean enter, int transitionStyle) { Animatable animObj = fragment.onCreateAnimatable(transit, enter, @@ -387,6 +522,7 @@ public class FragmentManager { return; } + if (DEBUG) Log.v(TAG, "Freeing fragment index " + f.mIndex); mActive.set(f.mIndex, null); if (mAvailIndices == null) { mAvailIndices = new ArrayList<Integer>(); @@ -636,17 +772,6 @@ public class FragmentManager { mBackStack.add(state); } - public boolean popBackStackState(Handler handler, String name, int flags) { - return popBackStackState(handler, name, -1, flags); - } - - public boolean popBackStackState(Handler handler, int id, int flags) { - if (id < 0) { - return false; - } - return popBackStackState(handler, null, id, flags); - } - boolean popBackStackState(Handler handler, String name, int id, int flags) { if (mBackStack == null) { return false; @@ -787,10 +912,13 @@ public class FragmentManager { } } + if (DEBUG) Log.v(TAG, "Saved state of " + f + ": " + + fs.mSavedFragmentState); } } if (!haveFragments) { + if (DEBUG) Log.v(TAG, "saveAllState: no fragments!"); return null; } @@ -803,6 +931,8 @@ public class FragmentManager { added = new int[N]; for (int i=0; i<N; i++) { added[i] = mAdded.get(i).mIndex; + if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i + + ": " + mAdded.get(i)); } } @@ -813,6 +943,8 @@ public class FragmentManager { backStack = new BackStackState[N]; for (int i=0; i<N; i++) { backStack[i] = new BackStackState(this, mBackStack.get(i)); + if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i + + ": " + mBackStack.get(i)); } } } @@ -836,6 +968,7 @@ public class FragmentManager { if (nonConfig != null) { for (int i=0; i<nonConfig.size(); i++) { Fragment f = nonConfig.get(i); + if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f); FragmentState fs = fms.mActive[f.mIndex]; fs.mInstance = f; f.mSavedViewState = null; @@ -857,12 +990,16 @@ public class FragmentManager { for (int i=0; i<fms.mActive.length; i++) { FragmentState fs = fms.mActive[i]; if (fs != null) { - mActive.add(fs.instantiate(mActivity)); + Fragment f = fs.instantiate(mActivity); + if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": " + f); + mActive.add(f); } else { + if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": (null)"); mActive.add(null); if (mAvailIndices == null) { mAvailIndices = new ArrayList<Integer>(); } + if (DEBUG) Log.v(TAG, "restoreAllState: adding avail #" + i); mAvailIndices.add(i); } } @@ -878,6 +1015,7 @@ public class FragmentManager { } f.mAdded = true; f.mImmediateActivity = mActivity; + if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f); mAdded.add(f); } } else { @@ -889,6 +1027,8 @@ public class FragmentManager { mBackStack = new ArrayList<BackStackEntry>(fms.mBackStack.length); for (int i=0; i<fms.mBackStack.length; i++) { BackStackEntry bse = fms.mBackStack[i].instantiate(this); + if (DEBUG) Log.v(TAG, "restoreAllState: adding bse #" + i + + " (index " + bse.mIndex + "): " + bse); mBackStack.add(bse); if (bse.mIndex >= 0) { setBackStackIndex(bse.mIndex, bse); diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index 114f67d..32bf170 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -113,9 +113,28 @@ public abstract class PreferenceActivity extends ListActivity implements private static final String PREFERENCES_TAG = "android:preferences"; - private static final String EXTRA_PREFS_SHOW_FRAGMENT = ":android:show_fragment"; + /** + * When starting this activity, the invoking Intent can contain this extra + * string to specify which fragment should be initially displayed. + */ + public static final String EXTRA_SHOW_FRAGMENT = ":android:show_fragment"; - private static final String EXTRA_PREFS_NO_HEADERS = ":android:no_headers"; + /** + * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT}, + * this extra can also be specify to supply a Bundle of arguments to pass + * to that fragment when it is instantiated during the initial creation + * of PreferenceActivity. + */ + public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":android:show_fragment_args"; + + /** + * When starting this activity, the invoking Intent can contain this extra + * boolean that the header list should not be displayed. This is most often + * used in conjunction with {@link #EXTRA_SHOW_FRAGMENT} to launch + * the activity to display a specific fragment that the user has navigated + * to. + */ + public static final String EXTRA_NO_HEADERS = ":android:no_headers"; private static final String BACK_STACK_PREFS = ":android:prefs"; @@ -159,14 +178,18 @@ public abstract class PreferenceActivity extends ListActivity implements private static final int FIRST_REQUEST_CODE = 100; private static final int MSG_BIND_PREFERENCES = 0; + private static final int MSG_BUILD_HEADERS = 1; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_BIND_PREFERENCES: bindPreferences(); break; + case MSG_BUILD_HEADERS: + onBuildHeaders(mHeaders); + mAdapter.notifyDataSetChanged(); + break; } } }; @@ -250,6 +273,12 @@ public abstract class PreferenceActivity extends ListActivity implements * @attr ref android.R.styleable#PreferenceHeader_fragment */ String fragment; + + /** + * Optional arguments to supply to the fragment when it is + * instantiated. + */ + Bundle fragmentArguments; } @Override @@ -261,7 +290,8 @@ public abstract class PreferenceActivity extends ListActivity implements mPrefsContainer = findViewById(com.android.internal.R.id.prefs); boolean hidingHeaders = onIsHidingHeaders(); mSinglePane = hidingHeaders || !onIsMultiPane(); - String initialFragment = getIntent().getStringExtra(EXTRA_PREFS_SHOW_FRAGMENT); + String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT); + Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS); if (initialFragment != null && mSinglePane) { // If we are just showing a fragment, we want to run in @@ -269,7 +299,7 @@ public abstract class PreferenceActivity extends ListActivity implements // the headers. getListView().setVisibility(View.GONE); mPrefsContainer.setVisibility(View.VISIBLE); - switchToHeader(initialFragment); + switchToHeader(initialFragment, initialArguments); } else { // We need to try to build the headers. @@ -283,8 +313,12 @@ public abstract class PreferenceActivity extends ListActivity implements setListAdapter(mAdapter); if (!mSinglePane) { mPrefsContainer.setVisibility(View.VISIBLE); - switchToHeader(initialFragment != null - ? initialFragment : onGetInitialFragment()); + if (initialFragment != null) { + Header h = onGetInitialHeader(); + initialFragment = h.fragment; + initialArguments = h.fragmentArguments; + } + switchToHeader(initialFragment, initialArguments); } // If there are no headers, we are in the old "just show a screen @@ -371,15 +405,18 @@ public abstract class PreferenceActivity extends ListActivity implements * when not in multi-pane mode. */ public boolean onIsHidingHeaders() { - return getIntent().getBooleanExtra(EXTRA_PREFS_NO_HEADERS, false); + return getIntent().getBooleanExtra(EXTRA_NO_HEADERS, false); } /** - * Called to determine the initial fragment to be shown. The default - * implementation simply returns the fragment of the first header. + * Called to determine the initial header to be shown. The default + * implementation simply returns the fragment of the first header. Note + * that the returned Header object does not actually need to exist in + * your header list -- whatever its fragment is will simply be used to + * show for the initial UI. */ - public String onGetInitialFragment() { - return mHeaders.get(0).fragment; + public Header onGetInitialHeader() { + return mHeaders.get(0); } /** @@ -399,6 +436,16 @@ public abstract class PreferenceActivity extends ListActivity implements } /** + * Call when you need to change the headers being displayed. Will result + * in onBuildHeaders() later being called to retrieve the new list. + */ + public void invalidateHeaders() { + if (!mHandler.hasMessages(MSG_BUILD_HEADERS)) { + mHandler.sendEmptyMessage(MSG_BUILD_HEADERS); + } + } + + /** * Parse the given XML file as a header description, adding each * parsed Header into the target list. * @@ -544,17 +591,17 @@ 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)} - * or {@link #switchToHeader(String)} as appropriate. + * implementation will call either {@link #startWithFragment(String, Bundle)} + * or {@link #switchToHeader(String, Bundle)} as appropriate. * * @param header The header that was selected. * @param position The header's position in the list. */ public void onHeaderClick(Header header, int position) { if (mSinglePane) { - startWithFragment(header.fragment); + startWithFragment(header.fragment, header.fragmentArguments); } else { - switchToHeader(header.fragment); + switchToHeader(header.fragment, header.fragmentArguments); } } @@ -565,12 +612,14 @@ public abstract class PreferenceActivity extends ListActivity implements * and fill the entire activity. * * @param fragmentName The name of the fragment to display. + * @param args Optional arguments to supply to the fragment. */ - public void startWithFragment(String fragmentName) { + public void startWithFragment(String fragmentName, Bundle args) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClass(this, getClass()); - intent.putExtra(EXTRA_PREFS_SHOW_FRAGMENT, fragmentName); - intent.putExtra(EXTRA_PREFS_NO_HEADERS, true); + intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName); + intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args); + intent.putExtra(EXTRA_NO_HEADERS, true); startActivity(intent); } @@ -579,29 +628,18 @@ public abstract class PreferenceActivity extends ListActivity implements * preference fragment. * * @param fragmentName The name of the fragment to display. + * @param args Optional arguments to supply to the fragment. */ - public void switchToHeader(String fragmentName) { + public void switchToHeader(String fragmentName, Bundle args) { popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE); - Fragment f; - try { - f = Fragment.instantiate(this, fragmentName); - } catch (Exception e) { - Log.w(TAG, "Failure instantiating fragment " + fragmentName, e); - return; - } + Fragment f = Fragment.instantiate(this, fragmentName, args); openFragmentTransaction().replace(com.android.internal.R.id.prefs, f).commit(); } @Override public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { - Fragment f; - try { - f = Fragment.instantiate(this, pref.getFragment()); - } catch (Exception e) { - Log.w(TAG, "Failure instantiating fragment " + pref.getFragment(), e); - return false; - } + Fragment f = Fragment.instantiate(this, pref.getFragment()); openFragmentTransaction().replace(com.android.internal.R.id.prefs, f) .addToBackStack(BACK_STACK_PREFS).commit(); return true; diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java index f34f4a3..c7f8ab2 100644 --- a/core/java/android/preference/PreferenceScreen.java +++ b/core/java/android/preference/PreferenceScreen.java @@ -91,7 +91,8 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi /** * Returns an adapter that can be attached to a {@link PreferenceActivity} - * to show the preferences contained in this {@link PreferenceScreen}. + * or {@link PreferenceFragment} to show the preferences contained in this + * {@link PreferenceScreen}. * <p> * This {@link PreferenceScreen} will NOT appear in the returned adapter, instead * it appears in the hierarchy above this {@link PreferenceScreen}. diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 48d5345..c93d9b2 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -32,6 +32,7 @@ import android.database.Cursor; import android.database.DatabaseUtils; import android.graphics.Rect; import android.net.Uri; +import android.net.Uri.Builder; import android.os.RemoteException; import android.text.TextUtils; import android.util.DisplayMetrics; @@ -40,6 +41,7 @@ import android.view.View; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.util.ArrayList; /** * <p> @@ -1487,6 +1489,106 @@ public final class ContactsContract { * {@link android.provider.ContactsContract.Contacts#CONTENT_FILTER_URI}. */ public static final String CONTENT_DIRECTORY = "suggestions"; + + /** + * Used with {@link Builder#addParameter} to specify what kind of data is + * supplied for the suggestion query. + * + * @hide + */ + public static final String PARAMETER_MATCH_NAME = "name"; + + /** + * Used with {@link Builder#addParameter} to specify what kind of data is + * supplied for the suggestion query. + * + * @hide + */ + public static final String PARAMETER_MATCH_EMAIL = "email"; + + /** + * Used with {@link Builder#addParameter} to specify what kind of data is + * supplied for the suggestion query. + * + * @hide + */ + public static final String PARAMETER_MATCH_PHONE = "phone"; + + /** + * Used with {@link Builder#addParameter} to specify what kind of data is + * supplied for the suggestion query. + * + * @hide + */ + public static final String PARAMETER_MATCH_NICKNAME = "nickname"; + + /** + * A convenience builder for aggregation suggestion content URIs. + * + * TODO: change documentation for this class to use the builder. + * @hide + */ + public static final class Builder { + private long mContactId; + private ArrayList<String> mKinds = new ArrayList<String>(); + private ArrayList<String> mValues = new ArrayList<String>(); + private int mLimit; + + /** + * Optional existing contact ID. If it is not provided, the search + * will be based exclusively on the values supplied with {@link #addParameter}. + */ + public Builder setContactId(long contactId) { + this.mContactId = contactId; + return this; + } + + /** + * A value that can be used when searching for an aggregation + * suggestion. + * + * @param kind can be one of + * {@link AggregationSuggestions#PARAMETER_MATCH_NAME}, + * {@link AggregationSuggestions#PARAMETER_MATCH_EMAIL}, + * {@link AggregationSuggestions#PARAMETER_MATCH_NICKNAME}, + * {@link AggregationSuggestions#PARAMETER_MATCH_PHONE} + */ + public Builder addParameter(String kind, String value) { + if (!TextUtils.isEmpty(value)) { + mKinds.add(kind); + mValues.add(value); + } + return this; + } + + public Builder setLimit(int limit) { + mLimit = limit; + return this; + } + + public Uri build() { + android.net.Uri.Builder builder = Contacts.CONTENT_URI.buildUpon(); + builder.appendEncodedPath(String.valueOf(mContactId)); + builder.appendPath(Contacts.AggregationSuggestions.CONTENT_DIRECTORY); + if (mLimit != 0) { + builder.appendQueryParameter("limit", String.valueOf(mLimit)); + } + + int count = mKinds.size(); + for (int i = 0; i < count; i++) { + builder.appendQueryParameter("query", mKinds.get(i) + ":" + mValues.get(i)); + } + + return builder.build(); + } + } + + /** + * @hide + */ + public static final Builder builder() { + return new Builder(); + } } /** diff --git a/core/java/android/util/AndroidException.java b/core/java/android/util/AndroidException.java index a767ea1..dfe00c9 100644 --- a/core/java/android/util/AndroidException.java +++ b/core/java/android/util/AndroidException.java @@ -27,6 +27,10 @@ public class AndroidException extends Exception { super(name); } + public AndroidException(String name, Throwable cause) { + super(name, cause); + } + public AndroidException(Exception cause) { super(cause); } diff --git a/core/java/android/util/AndroidRuntimeException.java b/core/java/android/util/AndroidRuntimeException.java index 4ed17bc..2b824bf 100644 --- a/core/java/android/util/AndroidRuntimeException.java +++ b/core/java/android/util/AndroidRuntimeException.java @@ -27,6 +27,10 @@ public class AndroidRuntimeException extends RuntimeException { super(name); } + public AndroidRuntimeException(String name, Throwable cause) { + super(name, cause); + } + public AndroidRuntimeException(Exception cause) { super(cause); } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 32009be..9f60f44 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -3557,11 +3557,11 @@ public class WebView extends AbsoluteLayout InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - // bring it back to the default scale so that user can enter text - boolean zoom = mZoomManager.getScale() < mZoomManager.getDefaultScale(); + // bring it back to the reading level scale so that user can enter text + boolean zoom = mZoomManager.getScale() < mZoomManager.getReadingLevelScale(); if (zoom) { mZoomManager.setZoomCenter(mLastTouchX, mLastTouchY); - mZoomManager.setZoomScale(mZoomManager.getDefaultScale(), false); + mZoomManager.setZoomScale(mZoomManager.getReadingLevelScale(), false); } if (isTextView) { rebuildWebTextView(); diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index 7f7f46e..8033c9c 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -56,6 +56,13 @@ class ZoomManager { private ZoomControlExternal mExternalZoomControl; /* + * For large screen devices, the defaultScale usually set to 1.0 and + * equal to the overview scale, to differentiate the zoom level for double tapping, + * a minimum reading level scale is used. + */ + private static final float MIN_READING_LEVEL_SCALE = 1.5f; + + /* * The scale factors that determine the upper and lower bounds for the * default zoom scale. */ @@ -245,6 +252,10 @@ class ZoomManager { return mDefaultScale; } + public final float getReadingLevelScale() { + return Math.max(mDefaultScale, MIN_READING_LEVEL_SCALE); + } + public final float getInvDefaultScale() { return mInvDefaultScale; } @@ -337,9 +348,9 @@ class ZoomManager { mInitialScrollX = mWebView.getScrollX(); mInitialScrollY = mWebView.getScrollY(); - // snap to DEFAULT_SCALE if it is close - if (!exceedsMinScaleIncrement(scale, mDefaultScale)) { - scale = mDefaultScale; + // snap to reading level scale if it is close + if (!exceedsMinScaleIncrement(scale, getReadingLevelScale())) { + scale = getReadingLevelScale(); } setZoomScale(scale, reflowText); @@ -535,7 +546,7 @@ class ZoomManager { } else if (!mInZoomOverview) { zoomToOverview(); } else { - zoomToDefaultLevel(); + zoomToReadingLevel(); } } @@ -563,7 +574,8 @@ class ZoomManager { startZoomAnimation(getZoomOverviewScale(), true); } - private void zoomToDefaultLevel() { + private void zoomToReadingLevel() { + final float readingScale = getReadingLevelScale(); int left = mWebView.nativeGetBlockLeftEdge(mAnchorX, mAnchorY, mActualScale); if (left != WebView.NO_LEFTEDGE) { // add a 5pt padding to the left edge. @@ -572,13 +584,13 @@ class ZoomManager { // Re-calculate the zoom center so that the new scroll x will be // on the left edge. if (viewLeft > 0) { - mZoomCenterX = viewLeft * mDefaultScale / (mDefaultScale - mActualScale); + mZoomCenterX = viewLeft * readingScale / (readingScale - mActualScale); } else { mWebView.scrollBy(viewLeft, 0); mZoomCenterX = 0; } } - startZoomAnimation(mDefaultScale, true); + startZoomAnimation(readingScale, true); } public void updateMultiTouchSupport(Context context) { diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java index 2b723c9..ef00d88 100644 --- a/core/java/android/widget/AdapterViewAnimator.java +++ b/core/java/android/widget/AdapterViewAnimator.java @@ -685,14 +685,6 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> verticalOffset = 0; } - void setHorizontalOffset(int newHorizontalOffset) { - horizontalOffset = newHorizontalOffset; - if (mView != null) { - mView.requestLayout(); - mView.invalidate(); - } - } - private Rect parentRect = new Rect(); void invalidateGlobalRegion(View v, Rect r) { View p = v; @@ -722,5 +714,17 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> invalidateGlobalRegion(mView, invalidateRect); } } + + public void setHorizontalOffset(int newHorizontalOffset) { + int offsetDelta = newHorizontalOffset - horizontalOffset; + horizontalOffset = newHorizontalOffset; + if (mView != null) { + mView.requestLayout(); + int left = Math.min(mView.getLeft() + offsetDelta, mView.getLeft()); + int right = Math.max(mView.getRight() + offsetDelta, mView.getRight()); + invalidateRect.set(left, mView.getTop(), right, mView.getBottom()); + invalidateGlobalRegion(mView, invalidateRect); + } + } } } diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index 4cd44d9..e3aca6a 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -20,6 +20,12 @@ import java.util.WeakHashMap; import android.animation.PropertyAnimator; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; @@ -72,11 +78,9 @@ public class StackView extends AdapterViewAnimator { * These variables are all related to the current state of touch interaction * with the stack */ - private boolean mGestureComplete = false; private float mInitialY; private float mInitialX; private int mActivePointerId; - private int mYOffset = 0; private int mYVelocity = 0; private int mSwipeGestureType = GESTURE_NONE; private int mViewHeight; @@ -85,6 +89,8 @@ public class StackView extends AdapterViewAnimator { private int mMaximumVelocity; private VelocityTracker mVelocityTracker; + private ImageView mHighlight; + private StackSlider mStackSlider; private boolean mFirstLayoutHappened = false; // TODO: temp hack to get this thing started @@ -107,6 +113,15 @@ public class StackView extends AdapterViewAnimator { mTouchSlop = configuration.getScaledTouchSlop();// + 5; mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mActivePointerId = INVALID_POINTER; + + mHighlight = new ImageView(getContext()); + mHighlight.setLayoutParams(new LayoutParams(mHighlight)); + addViewInLayout(mHighlight, -1, new LayoutParams(mHighlight)); + mStackSlider = new StackSlider(); + + if (!sPaintsInitialized) { + initializePaints(getContext()); + } } /** @@ -124,6 +139,7 @@ public class StackView extends AdapterViewAnimator { } else if (fromIndex == mNumActiveViews - 1 && toIndex == mNumActiveViews - 2) { // Slide item in view.setVisibility(VISIBLE); + LayoutParams lp = (LayoutParams) view.getLayoutParams(); int largestDuration = (int) Math.round( @@ -136,19 +152,18 @@ public class StackView extends AdapterViewAnimator { duration = Math.min(duration, largestDuration); duration = Math.max(duration, MINIMUM_ANIMATION_DURATION); - PropertyAnimator slideDown = new PropertyAnimator(duration, lp, - "verticalOffset", lp.verticalOffset, 0); - slideDown.start(); + PropertyAnimator slideInY = new PropertyAnimator(duration, mStackSlider, + "YProgress", mStackSlider.getYProgress(), 0); + slideInY.start(); + PropertyAnimator slideInX = new PropertyAnimator(duration, mStackSlider, + "XProgress", mStackSlider.getXProgress(), 0); + slideInX.start(); - PropertyAnimator fadeIn = new PropertyAnimator(duration, view, - "alpha", view.getAlpha(), 1.0f); - fadeIn.start(); } else if (fromIndex == mNumActiveViews - 2 && toIndex == mNumActiveViews - 1) { // Slide item out LayoutParams lp = (LayoutParams) view.getLayoutParams(); - int largestDuration = (int) Math.round( - (1 - (lp.verticalOffset*1.0f/-mViewHeight))*DEFAULT_ANIMATION_DURATION); + int largestDuration = (int) Math.round(mStackSlider.getYProgress()*DEFAULT_ANIMATION_DURATION); int duration = largestDuration; if (mYVelocity != 0) { duration = 1000*(lp.verticalOffset + mViewHeight)/Math.abs(mYVelocity); @@ -157,13 +172,13 @@ public class StackView extends AdapterViewAnimator { duration = Math.min(duration, largestDuration); duration = Math.max(duration, MINIMUM_ANIMATION_DURATION); - PropertyAnimator slideUp = new PropertyAnimator(duration, lp, - "verticalOffset", lp.verticalOffset, -mViewHeight); - slideUp.start(); + PropertyAnimator slideOutY = new PropertyAnimator(duration, mStackSlider, + "YProgress", mStackSlider.getYProgress(), 1); + slideOutY.start(); + PropertyAnimator slideOutX = new PropertyAnimator(duration, mStackSlider, + "XProgress", mStackSlider.getXProgress(), 0); + slideOutX.start(); - PropertyAnimator fadeOut = new PropertyAnimator(duration, view, - "alpha", view.getAlpha(), 0.0f); - fadeOut.start(); } else if (fromIndex == -1 && toIndex == mNumActiveViews - 1) { // Make sure this view that is "waiting in the wings" is invisible view.setAlpha(0.0f); @@ -233,7 +248,6 @@ public class StackView extends AdapterViewAnimator { view.setClipChildren(false); view.setClipToPadding(false); } - mFirstLayoutHappened = true; } } @@ -258,16 +272,10 @@ public class StackView extends AdapterViewAnimator { Log.d(TAG, "Error: No data for our primary pointer."); return false; } - float newY = ev.getY(pointerIndex); float deltaY = newY - mInitialY; - if ((int) Math.abs(deltaY) > mTouchSlop && mSwipeGestureType == GESTURE_NONE) { - mSwipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN; - mGestureComplete = false; - cancelLongPress(); - requestDisallowInterceptTouchEvent(true); - } + beginGestureIfNeeded(deltaY); break; } case MotionEvent.ACTION_POINTER_UP: { @@ -278,13 +286,33 @@ public class StackView extends AdapterViewAnimator { case MotionEvent.ACTION_CANCEL: { mActivePointerId = INVALID_POINTER; mSwipeGestureType = GESTURE_NONE; - mGestureComplete = true; } } return mSwipeGestureType != GESTURE_NONE; } + private void beginGestureIfNeeded(float deltaY) { + if ((int) Math.abs(deltaY) > mTouchSlop && mSwipeGestureType == GESTURE_NONE) { + mSwipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN; + cancelLongPress(); + requestDisallowInterceptTouchEvent(true); + + int activeIndex = mSwipeGestureType == GESTURE_SLIDE_DOWN ? mNumActiveViews - 1 + : mNumActiveViews - 2; + + View v = getViewAtRelativeIndex(activeIndex); + if (v != null) { + mHighlight.setImageBitmap(createOutline(v)); + mHighlight.bringToFront(); + v.bringToFront(); + mStackSlider.setView(v); + if (mSwipeGestureType == GESTURE_SLIDE_DOWN) + v.setVisibility(VISIBLE); + } + } + } + @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); @@ -296,8 +324,9 @@ public class StackView extends AdapterViewAnimator { } float newY = ev.getY(pointerIndex); + float newX = ev.getX(pointerIndex); float deltaY = newY - mInitialY; - + float deltaX = newX - mInitialX; if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } @@ -305,48 +334,21 @@ public class StackView extends AdapterViewAnimator { switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_MOVE: { - if ((int) Math.abs(deltaY) > mTouchSlop && mSwipeGestureType == GESTURE_NONE) { - mSwipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN; - mGestureComplete = false; - cancelLongPress(); - requestDisallowInterceptTouchEvent(true); + beginGestureIfNeeded(deltaY); + + float rx = 0.3f*deltaX/(mViewHeight*1.0f); + if (mSwipeGestureType == GESTURE_SLIDE_DOWN) { + float r = (deltaY-mTouchSlop*1.0f)/mViewHeight*1.0f; + mStackSlider.setYProgress(1 - r); + mStackSlider.setXProgress(rx); + return true; + } else if (mSwipeGestureType == GESTURE_SLIDE_UP) { + float r = -(deltaY + mTouchSlop*1.0f)/mViewHeight*1.0f; + mStackSlider.setYProgress(r); + mStackSlider.setXProgress(rx); + return true; } - if (!mGestureComplete) { - if (mSwipeGestureType == GESTURE_SLIDE_DOWN) { - View v = getViewAtRelativeIndex(mNumActiveViews - 1); - if (v != null) { - // This view is present but hidden, make sure it's visible - // if they pull down - v.setVisibility(VISIBLE); - - float r = (deltaY-mTouchSlop)*1.0f / (mSwipeThreshold); - mYOffset = Math.min(-mViewHeight + (int) Math.round( - r*mSwipeThreshold) - mTouchSlop, 0); - LayoutParams lp = (LayoutParams) v.getLayoutParams(); - lp.setVerticalOffset(mYOffset); - - float alpha = Math.max(0.0f, 1.0f - (1.0f*mYOffset/-mViewHeight)); - alpha = Math.min(1.0f, alpha); - v.setAlpha(alpha); - } - return true; - } else if (mSwipeGestureType == GESTURE_SLIDE_UP) { - View v = getViewAtRelativeIndex(mNumActiveViews - 2); - - if (v != null) { - float r = -(deltaY*1.0f + mTouchSlop) / (mSwipeThreshold); - mYOffset = Math.min((int) Math.round(r*-mSwipeThreshold), 0); - LayoutParams lp = (LayoutParams) v.getLayoutParams(); - lp.setVerticalOffset(mYOffset); - - float alpha = Math.max(0.0f, 1.0f - (1.0f*mYOffset/-mViewHeight)); - alpha = Math.min(1.0f, alpha); - v.setAlpha(alpha); - } - return true; - } - } break; } case MotionEvent.ACTION_UP: { @@ -359,9 +361,7 @@ public class StackView extends AdapterViewAnimator { } case MotionEvent.ACTION_CANCEL: { mActivePointerId = INVALID_POINTER; - mGestureComplete = true; mSwipeGestureType = GESTURE_NONE; - mYOffset = 0; break; } } @@ -427,56 +427,108 @@ public class StackView extends AdapterViewAnimator { mVelocityTracker = null; } - if (deltaY > mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_DOWN && - !mGestureComplete) { + if (deltaY > mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_DOWN) { // Swipe threshold exceeded, swipe down showNext(); - } else if (deltaY < -mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_UP && - !mGestureComplete) { + mHighlight.bringToFront(); + } else if (deltaY < -mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_UP) { // Swipe threshold exceeded, swipe up showPrevious(); - } else if (mSwipeGestureType == GESTURE_SLIDE_UP && !mGestureComplete) { + mHighlight.bringToFront(); + } else if (mSwipeGestureType == GESTURE_SLIDE_UP) { // Didn't swipe up far enough, snap back down - View v = getViewAtRelativeIndex(mNumActiveViews - 2); - if (v != null) { - // Compute the animation duration based on how far they pulled it up - LayoutParams lp = (LayoutParams) v.getLayoutParams(); - int duration = (int) Math.round( - lp.verticalOffset*1.0f/-mViewHeight*DEFAULT_ANIMATION_DURATION); - duration = Math.max(MINIMUM_ANIMATION_DURATION, duration); - - // Animate back down - PropertyAnimator slideDown = new PropertyAnimator(duration, lp, - "verticalOffset", lp.verticalOffset, 0); - slideDown.start(); - PropertyAnimator fadeIn = new PropertyAnimator(duration, v, - "alpha",v.getAlpha(), 1.0f); - fadeIn.start(); - } - } else if (mSwipeGestureType == GESTURE_SLIDE_DOWN && !mGestureComplete) { + int duration = (int) Math.round(mStackSlider.getYProgress()*DEFAULT_ANIMATION_DURATION); + + PropertyAnimator snapBackY = new PropertyAnimator(duration, mStackSlider, + "YProgress", mStackSlider.getYProgress(), 0); + snapBackY.start(); + PropertyAnimator snapBackX = new PropertyAnimator(duration, mStackSlider, + "XProgress", mStackSlider.getXProgress(), 0); + snapBackX.start(); + } else if (mSwipeGestureType == GESTURE_SLIDE_DOWN) { // Didn't swipe down far enough, snap back up - View v = getViewAtRelativeIndex(mNumActiveViews - 1); - if (v != null) { - // Compute the animation duration based on how far they pulled it down - LayoutParams lp = (LayoutParams) v.getLayoutParams(); - int duration = (int) Math.round( - (1 - lp.verticalOffset*1.0f/-mViewHeight)*DEFAULT_ANIMATION_DURATION); - duration = Math.max(MINIMUM_ANIMATION_DURATION, duration); - - // Animate back up - PropertyAnimator slideUp = new PropertyAnimator(duration, lp, - "verticalOffset", lp.verticalOffset, -mViewHeight); - slideUp.start(); - PropertyAnimator fadeOut = new PropertyAnimator(duration, v, - "alpha",v.getAlpha(), 0.0f); - fadeOut.start(); - } + int duration = (int) Math.round((1 - + mStackSlider.getYProgress())*DEFAULT_ANIMATION_DURATION); + PropertyAnimator snapBackY = new PropertyAnimator(duration, mStackSlider, + "YProgress", mStackSlider.getYProgress(), 1); + snapBackY.start(); + PropertyAnimator snapBackX = new PropertyAnimator(duration, mStackSlider, + "XProgress", mStackSlider.getXProgress(), 0); + snapBackX.start(); } mActivePointerId = INVALID_POINTER; - mGestureComplete = true; mSwipeGestureType = GESTURE_NONE; - mYOffset = 0; + } + + private class StackSlider { + View mView; + float mYProgress; + float mXProgress; + + private float cubic(float r) { + return (float) (Math.pow(2*r-1, 3) + 1)/2.0f; + } + + private float highlightAlphaInterpolator(float r) { + float pivot = 0.4f; + if (r < pivot) { + return 0.85f*cubic(r/pivot); + } else { + return 0.85f*cubic(1 - (r-pivot)/(1-pivot)); + } + } + + private float viewAlphaInterpolator(float r) { + float pivot = 0.3f; + if (r > pivot) { + return (r - pivot)/(1 - pivot); + } else { + return 0; + } + } + + void setView(View v) { + mView = v; + } + + public void setYProgress(float r) { + // enforce r between 0 and 1 + r = Math.min(1.0f, r); + r = Math.max(0, r); + + mYProgress = r; + + final LayoutParams viewLp = (LayoutParams) mView.getLayoutParams(); + final LayoutParams highlightLp = (LayoutParams) mHighlight.getLayoutParams(); + + viewLp.setVerticalOffset((int) Math.round(-r*mViewHeight)); + highlightLp.setVerticalOffset((int) Math.round(-r*mViewHeight)); + mHighlight.setAlpha(highlightAlphaInterpolator(r)); + mView.setAlpha(viewAlphaInterpolator(1-r)); + } + + public void setXProgress(float r) { + // enforce r between 0 and 1 + r = Math.min(1.0f, r); + r = Math.max(-1.0f, r); + + mXProgress = r; + + final LayoutParams viewLp = (LayoutParams) mView.getLayoutParams(); + final LayoutParams highlightLp = (LayoutParams) mHighlight.getLayoutParams(); + + viewLp.setHorizontalOffset((int) Math.round(r*mViewHeight)); + highlightLp.setHorizontalOffset((int) Math.round(r*mViewHeight)); + } + + float getYProgress() { + return mYProgress; + } + + float getXProgress() { + return mXProgress; + } } @Override @@ -484,4 +536,49 @@ public class StackView extends AdapterViewAnimator { super.onRemoteAdapterConnected(); setDisplayedChild(mIndex); } + + private static final Paint sHolographicPaint = new Paint(); + private static final Paint sErasePaint = new Paint(); + private static boolean sPaintsInitialized = false; + private static final float STROKE_WIDTH = 3.0f; + + static void initializePaints(Context context) { + sHolographicPaint.setColor(0xff6699ff); + sHolographicPaint.setFilterBitmap(true); + sErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + sErasePaint.setFilterBitmap(true); + sPaintsInitialized = true; + } + + static Bitmap createOutline(View v) { + Bitmap bitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + + canvas.concat(v.getMatrix()); + v.draw(canvas); + + Bitmap outlineBitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), + Bitmap.Config.ARGB_8888); + Canvas outlineCanvas = new Canvas(outlineBitmap); + drawOutline(outlineCanvas, v.getMeasuredWidth(), v.getMeasuredHeight(), bitmap); + bitmap.recycle(); + return outlineBitmap; + } + + static void drawOutline(Canvas dest, int destWidth, int destHeight, Bitmap src) { + dest.drawColor(0, PorterDuff.Mode.CLEAR); + + Bitmap mask = src.extractAlpha(); + Matrix id = new Matrix(); + + Matrix m = new Matrix(); + float xScale = STROKE_WIDTH*2/(src.getWidth()); + float yScale = STROKE_WIDTH*2/(src.getHeight()); + m.preScale(1+xScale, 1+yScale, src.getWidth()/2, src.getHeight()/2); + dest.drawBitmap(mask, m, sHolographicPaint); + + dest.drawBitmap(src, id, sErasePaint); + mask.recycle(); + } } diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index dd2ad6c..75084db 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -110,6 +110,7 @@ public class ActionBarImpl extends ActionBar { com.android.internal.R.id.lower_action_context_bar); mAnimatorView = (ViewAnimator) decor.findViewById( com.android.internal.R.id.action_bar_animator); + mActionView.setContextView(mUpperContextView); if (mActionView == null || mUpperContextView == null || mAnimatorView == null) { throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 6a476d0..8918a8e 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -27,6 +27,7 @@ import android.view.ActionMode; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.View.MeasureSpec; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; @@ -35,9 +36,6 @@ import android.widget.TextView; * @hide */ public class ActionBarContextView extends ViewGroup { - // TODO: This must be defined in the default theme - private static final int CONTENT_HEIGHT_DIP = 50; - private int mItemPadding; private int mItemMargin; private int mActionSpacing; @@ -75,11 +73,15 @@ public class ActionBarContextView extends ViewGroup { com.android.internal.R.styleable.Theme_actionModeCloseDrawable); mItemMargin = mItemPadding / 2; - mContentHeight = - (int) (CONTENT_HEIGHT_DIP * getResources().getDisplayMetrics().density + 0.5f); + mContentHeight = a.getLayoutDimension( + com.android.internal.R.styleable.Theme_windowActionBarSize, 0); a.recycle(); } + public void setHeight(int height) { + mContentHeight = height; + } + public void setCustomView(View view) { if (mCustomView != null) { removeView(mCustomView); @@ -208,8 +210,12 @@ public class ActionBarContextView extends ViewGroup { final int contentWidth = MeasureSpec.getSize(widthMeasureSpec); final int itemMargin = mItemPadding; + int maxHeight = mContentHeight > 0 ? + mContentHeight : MeasureSpec.getSize(heightMeasureSpec); + + final int verticalPadding = getPaddingTop() + getPaddingBottom(); int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight(); - final int height = mContentHeight - getPaddingTop() - getPaddingBottom(); + final int height = maxHeight - verticalPadding; final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); if (mCloseButton != null) { @@ -246,7 +252,20 @@ public class ActionBarContextView extends ViewGroup { MeasureSpec.makeMeasureSpec(customHeight, customHeightMode)); } - setMeasuredDimension(contentWidth, mContentHeight); + if (mContentHeight <= 0) { + int measuredHeight = 0; + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + View v = getChildAt(i); + int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; + if (paddedViewHeight > measuredHeight) { + measuredHeight = paddedViewHeight; + } + } + setMeasuredDimension(contentWidth, measuredHeight); + } else { + setMeasuredDimension(contentWidth, maxHeight); + } } @Override diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 73d3c95..c3c0db2 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -53,7 +53,6 @@ public class ActionBarView extends ViewGroup { private static final String TAG = "ActionBarView"; // TODO: This must be defined in the default theme - private static final int CONTENT_HEIGHT_DIP = 50; private static final int CONTENT_PADDING_DIP = 3; private static final int CONTENT_SPACING_DIP = 6; private static final int CONTENT_ACTION_SPACING_DIP = 12; @@ -90,12 +89,17 @@ public class ActionBarView extends ViewGroup { private LinearLayout mTabLayout; private View mCustomNavView; + private int mTitleStyleRes; + private int mSubtitleStyleRes; + private boolean mShowMenu; private boolean mUserTitle; private MenuBuilder mOptionsMenu; private ActionMenuView mMenuView; + private ActionBarContextView mContextView; + private ActionMenuItem mLogoNavItem; private NavigationCallback mCallback; @@ -151,6 +155,9 @@ public class ActionBarView extends ViewGroup { setBackgroundDrawable(background); } + mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0); + mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0); + final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0); if (customNavId != 0) { LayoutInflater inflater = LayoutInflater.from(context); @@ -159,11 +166,7 @@ public class ActionBarView extends ViewGroup { addView(mCustomNavView); } - final int padding = a.getDimensionPixelSize(R.styleable.ActionBar_padding, - (int) (CONTENT_PADDING_DIP * metrics.density + 0.5f)); - setPadding(padding, padding, padding, padding); - mContentHeight = a.getDimensionPixelSize(R.styleable.ActionBar_height, - (int) (CONTENT_PADDING_DIP * metrics.density + 0.5f)) - padding * 2; + mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0); a.recycle(); @@ -473,13 +476,22 @@ public class ActionBarView extends ViewGroup { mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null); mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title); mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle); + + if (mTitleStyleRes != 0) { + mTitleView.setTextAppearance(mContext, mTitleStyleRes); + } if (mTitle != null) { mTitleView.setText(mTitle); } + + if (mSubtitleStyleRes != 0) { + mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); + } if (mSubtitle != null) { mSubtitleView.setText(mSubtitle); mSubtitleView.setVisibility(VISIBLE); } + addView(mTitleLayout); } @@ -491,6 +503,10 @@ public class ActionBarView extends ViewGroup { } } + public void setContextView(ActionBarContextView view) { + mContextView = view; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); @@ -506,9 +522,13 @@ public class ActionBarView extends ViewGroup { } int contentWidth = MeasureSpec.getSize(widthMeasureSpec); + + int maxHeight = mContentHeight > 0 ? + mContentHeight : MeasureSpec.getSize(heightMeasureSpec); + final int verticalPadding = getPaddingTop() + getPaddingBottom(); int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight(); - final int height = mContentHeight - getPaddingTop() - getPaddingBottom(); + final int height = maxHeight - verticalPadding; final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); if (mLogoView != null && mLogoView.getVisibility() != GONE) { @@ -561,7 +581,24 @@ public class ActionBarView extends ViewGroup { break; } - setMeasuredDimension(contentWidth, mContentHeight); + if (mContentHeight <= 0) { + int measuredHeight = 0; + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + View v = getChildAt(i); + int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; + if (paddedViewHeight > measuredHeight) { + measuredHeight = paddedViewHeight; + } + } + setMeasuredDimension(contentWidth, measuredHeight); + } else { + setMeasuredDimension(contentWidth, maxHeight); + } + + if (mContextView != null) { + mContextView.setHeight(getMeasuredHeight()); + } } private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) { diff --git a/core/res/res/anim/push_down_in_no_alpha.xml b/core/res/res/anim/push_down_in_no_alpha.xml new file mode 100644 index 0000000..045d691 --- /dev/null +++ b/core/res/res/anim/push_down_in_no_alpha.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromYDelta="-100%p" android:toYDelta="0" + android:duration="@android:integer/config_longAnimTime"/> +</set> diff --git a/core/res/res/anim/push_down_out_no_alpha.xml b/core/res/res/anim/push_down_out_no_alpha.xml new file mode 100644 index 0000000..3c2474a --- /dev/null +++ b/core/res/res/anim/push_down_out_no_alpha.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <translate android:fromYDelta="0" android:toYDelta="100%p" + android:duration="@android:integer/config_longAnimTime"/> +</set> diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml index 41ce8e4..30a7318 100644 --- a/core/res/res/layout-xlarge/screen_action_bar.xml +++ b/core/res/res/layout-xlarge/screen_action_bar.xml @@ -24,8 +24,8 @@ This is an optimized layout for a screen with the Action Bar enabled. <ViewAnimator android:id="@+id/action_bar_animator" android:layout_width="match_parent" android:layout_height="wrap_content" - android:inAnimation="@anim/push_down_in" - android:outAnimation="@anim/push_down_out"> + android:inAnimation="@anim/push_down_in_no_alpha" + android:outAnimation="@anim/push_down_out_no_alpha"> <com.android.internal.widget.ActionBarView android:id="@+id/action_bar" android:layout_width="match_parent" diff --git a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml index d0277f0..cb35ac1 100644 --- a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml +++ b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml @@ -28,8 +28,8 @@ the Action Bar enabled overlaying application content. android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="top" - android:inAnimation="@anim/push_down_in" - android:outAnimation="@anim/push_down_out"> + android:inAnimation="@anim/push_down_in_no_alpha" + android:outAnimation="@anim/push_down_out_no_alpha"> <com.android.internal.widget.ActionBarView android:id="@+id/action_bar" android:layout_width="match_parent" @@ -41,6 +41,7 @@ the Action Bar enabled overlaying application content. android:layout_height="wrap_content" /> </ViewAnimator> <ImageView android:src="?android:attr/windowContentOverlay" + android:scaleType="fitXY" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/action_bar_animator" /> diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml index f39852b..3c44b8c 100644 --- a/core/res/res/layout/screen_action_bar.xml +++ b/core/res/res/layout/screen_action_bar.xml @@ -24,8 +24,8 @@ This is an optimized layout for a screen with the Action Bar enabled. <ViewAnimator android:id="@+id/action_bar_animator" android:layout_width="match_parent" android:layout_height="wrap_content" - android:inAnimation="@anim/push_down_in" - android:outAnimation="@anim/push_down_out"> + android:inAnimation="@anim/push_down_in_no_alpha" + android:outAnimation="@anim/push_down_out_no_alpha"> <com.android.internal.widget.ActionBarView android:id="@+id/action_bar" android:layout_width="match_parent" diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml index cb1ffc5..c854c6f 100644 --- a/core/res/res/layout/screen_action_bar_overlay.xml +++ b/core/res/res/layout/screen_action_bar_overlay.xml @@ -28,8 +28,8 @@ the Action Bar enabled overlaying application content. android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="top" - android:inAnimation="@anim/push_down_in" - android:outAnimation="@anim/push_down_out"> + android:inAnimation="@anim/push_down_in_no_alpha" + android:outAnimation="@anim/push_down_out_no_alpha"> <com.android.internal.widget.ActionBarView android:id="@+id/action_bar" android:layout_width="match_parent" @@ -41,6 +41,7 @@ the Action Bar enabled overlaying application content. android:layout_height="wrap_content" /> </ViewAnimator> <ImageView android:src="?android:attr/windowContentOverlay" + android:scaleType="fitXY" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/action_bar_animator" /> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index e768308..9c51aeb 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Dotykem zahájíte konfiguraci"</string> <string name="back_button_label" msgid="2300470004503343439">"Zpět"</string> <string name="next_button_label" msgid="1080555104677992408">"Další"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Vysoké využití mobilních dat"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Dotykem zobrazíte další informace o využití mobilních dat"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Byl překročen limit mobilních dat"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 2b67a2a..cf76818 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Tryk for at konfigurere"</string> <string name="back_button_label" msgid="2300470004503343439">"Tilbage"</string> <string name="next_button_label" msgid="1080555104677992408">"Næste"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Højt mobildataforbrug"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Tryk for oplysninger om brug af mobildata"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Grænsen for mobildata er overskredet"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 87376fe..712e10e 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Zum Konfigurieren berühren"</string> <string name="back_button_label" msgid="2300470004503343439">"Zurück"</string> <string name="next_button_label" msgid="1080555104677992408">"Weiter"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Hohe Mobildatennutzung"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Weitere Informationen über die Mobildatennutzung durch Berühren aufrufen"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Mobildatenlimit überschritten"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index c08e1da..9a6d9ee 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Αγγίξτε για να γίνει διαμόρφωση"</string> <string name="back_button_label" msgid="2300470004503343439">"Πίσω"</string> <string name="next_button_label" msgid="1080555104677992408">"Επόμενο"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Υψηλή χρήση δεδομένων κινητής τηλεφωνίας"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Αγγίξτε για να μάθετε περισσότερα σχετικά με τη χρήση δεδομένων κινητής τηλεφωνίας"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Ξεπεράστηκε το όριο δεδομένων κινητής τηλεφωνίας"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 26d329e..b720339 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Tocar para configurar"</string> <string name="back_button_label" msgid="2300470004503343439">"Atrás"</string> <string name="next_button_label" msgid="1080555104677992408">"Siguiente"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Amplia utilización de datos móviles"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Toca para obtener más información acerca de la utilización de datos móviles."</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Límite de datos móviles excedido "</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 8568211..0aeaf2e 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Toca para iniciar la configuración."</string> <string name="back_button_label" msgid="2300470004503343439">"Atrás"</string> <string name="next_button_label" msgid="1080555104677992408">"Siguiente"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Uso elevado datos móviles"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Más información sobre uso de datos"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Límite datos superado"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 04b6add..8884ddc 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Toucher pour configurer"</string> <string name="back_button_label" msgid="2300470004503343439">"Retour"</string> <string name="next_button_label" msgid="1080555104677992408">"Suivant"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Utilisation élevée des données mobiles"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Touchez pour en savoir plus sur l\'utilisation des données mobiles"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Quota d\'utilisation des données mobiles dépassé"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 7870ccf..0cf7f38 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Tocca per configurare"</string> <string name="back_button_label" msgid="2300470004503343439">"Indietro"</string> <string name="next_button_label" msgid="1080555104677992408">"Avanti"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Utilizzo dati cell. elevato"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Tocca per informazioni sull\'utilizzo dati cell."</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Limite dati cell. superato"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index a0b7e0e..468b692 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"タップして設定する"</string> <string name="back_button_label" msgid="2300470004503343439">"戻る"</string> <string name="next_button_label" msgid="1080555104677992408">"次へ"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"モバイルデータの使用量が増えています"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"タップしてモバイルデータ利用の詳細を表示します"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"モバイルデータの制限を超えました"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index bffb034..cb8f31b 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"구성하려면 터치하세요."</string> <string name="back_button_label" msgid="2300470004503343439">"뒤로"</string> <string name="next_button_label" msgid="1080555104677992408">"다음"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"높은 모바일 데이터 사용량"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"모바일 데이터 사용에 대해 자세히 알아보려면 터치하세요."</string> <string name="throttled_notification_title" msgid="6269541897729781332">"모바일 데이터 제한을 초과했습니다."</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 052eb08..4485d27 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Trykk for å konfigurere"</string> <string name="back_button_label" msgid="2300470004503343439">"Tilbake"</string> <string name="next_button_label" msgid="1080555104677992408">"Neste"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Høy mobildatabruk"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Berør for å lese mer om bruk av mobildata"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Grensen for mobildatabruk er overskredet"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 10ebc4e..abd791a 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Aanraken om te configureren"</string> <string name="back_button_label" msgid="2300470004503343439">"Vorige"</string> <string name="next_button_label" msgid="1080555104677992408">"Volgende"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Hoog mobiel gegevensgebruik"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Raak aan voor meer informatie over mobiel gegevensgebruik"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Mobiele gegevenslimiet overschreden"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 07946c7..28ba755 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Dotknij, aby skonfigurować"</string> <string name="back_button_label" msgid="2300470004503343439">"Wróć"</string> <string name="next_button_label" msgid="1080555104677992408">"Dalej"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Wysoki poziom użycia danych"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Dotknij, aby zobaczyć statystyki przesyłu danych"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Przekroczono limit danych"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index d44a80d..0cbc7c1 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Tocar para configurar"</string> <string name="back_button_label" msgid="2300470004503343439">"Anterior"</string> <string name="next_button_label" msgid="1080555104677992408">"Seguinte"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Utilização elevada de dados móveis"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Toque para saber mais sobre a utilização de dados móveis"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Limite de dados móveis excedido"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index a6c49d8..4f229d7 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Toque para configurar"</string> <string name="back_button_label" msgid="2300470004503343439">"Voltar"</string> <string name="next_button_label" msgid="1080555104677992408">"Avançar"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Alto uso de dados do celular"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Toque para saber mais sobre uso de dados do celular"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Limite de dados do celular excedido"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 21e8ad8..ff03e35 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Нажмите для настройки"</string> <string name="back_button_label" msgid="2300470004503343439">"Назад"</string> <string name="next_button_label" msgid="1080555104677992408">"Далее"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Активная передача данных"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Нажмите, чтобы узнать больше о мобильной передаче данных"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Превышен лимит на мобильные данные"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index e8f5a20..4d76987 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Tryck om du vill konfigurera"</string> <string name="back_button_label" msgid="2300470004503343439">"Tillbaka"</string> <string name="next_button_label" msgid="1080555104677992408">"Nästa"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Hög mobildataanvändning"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Tryck om du vill veta mer om mobildataanvändning"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Gränsen för mobildata har överskridits"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index a9dd887..b462c61 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"Yapılandırmak için dokunun"</string> <string name="back_button_label" msgid="2300470004503343439">"Geri"</string> <string name="next_button_label" msgid="1080555104677992408">"İleri"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Yüksek düzeyde mobil veri kullanımı"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Mobil veri kullanımı hakkında daha fazla bilgi edinmek için dokunun"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"Mobil veri limiti aşıldı"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 0949553..ff5d0e9 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"触摸可进行配置"</string> <string name="back_button_label" msgid="2300470004503343439">"上一步"</string> <string name="next_button_label" msgid="1080555104677992408">"下一步"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"手机流量过多"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"轻触以了解有关手机流量详情"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"已超出手机数据上限"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 2f0a49b..2e7bfdf 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -871,6 +871,8 @@ <string name="tethered_notification_message" msgid="3067108323903048927">"輕觸以設定"</string> <string name="back_button_label" msgid="2300470004503343439">"上一頁"</string> <string name="next_button_label" msgid="1080555104677992408">"下一頁"</string> + <!-- no translation found for skip_button_label (1275362299471631819) --> + <skip /> <string name="throttle_warning_notification_title" msgid="4890894267454867276">"高行動資料用量"</string> <string name="throttle_warning_notification_message" msgid="2609734763845705708">"輕觸即可瞭解更多有關行動資料用量的詳細資訊"</string> <string name="throttled_notification_title" msgid="6269541897729781332">"已達行動資料上限"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index a75f1a6..e0608f9 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -256,6 +256,12 @@ <!-- Reference to a style for the Action Bar --> <attr name="windowActionBarStyle" format="reference" /> + <!-- Size of the Action Bar, including the contextual + bar used to present Action Modes. --> + <attr name="windowActionBarSize" format="dimension" > + <enum name="wrap_content" value="0" /> + </attr> + <!-- Flag indicating whether action modes should overlay window content when there is not reserved space for their UI (such as an Action Bar). --> <attr name="windowActionModeOverlay" format="boolean" /> @@ -1005,6 +1011,7 @@ <attr name="windowActionBarStyle" /> <attr name="windowActionModeOverlay" /> <attr name="windowActionBarOverlay" /> + <attr name="windowActionBarSize" /> </declare-styleable> <!-- The set of attributes that describe a AlertDialog's theme. --> @@ -4003,8 +4010,6 @@ <attr name="customNavigationLayout" format="reference" /> <!-- Specifies a fixed height. --> <attr name="height" /> - <!-- Specifies padding around all sides. --> - <attr name="padding" /> </declare-styleable> </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 539f1c0..b84a613 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1320,6 +1320,8 @@ <public type="attr" name="fragmentOpenExitAnimation" /> <public type="attr" name="fragmentCloseEnterAnimation" /> <public type="attr" name="fragmentCloseExitAnimation" /> + <public type="attr" name="windowActionBarSize" /> + <public type="anim" name="animator_fade_in" /> <public type="anim" name="animator_fade_out" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 2b27930..a107048 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1610,7 +1610,7 @@ <!-- Do not translate. WebView User Agent string --> <string name="web_user_agent" translatable="false">Mozilla/5.0 (Linux; U; <xliff:g id="x">Android %s</xliff:g>) - AppleWebKit/534.5 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.5</string> + AppleWebKit/534.6 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.6</string> <!-- Do not translate. WebView User Agent targeted content --> <string name="web_user_agent_target_content" translatable="false">"Mobile "</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 7e52ebd..2ae3ccd 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -893,8 +893,11 @@ <item name="android:background">@android:drawable/action_bar_background</item> <item name="android:displayOptions">useLogo</item> <item name="android:divider">@android:drawable/action_bar_divider</item> - <item name="android:height">56dip</item> - <item name="android:padding">3dip</item> + <item name="android:height">?android:attr/windowActionBarSize</item> + <item name="android:paddingLeft">3dip</item> + <item name="android:paddingTop">3dip</item> + <item name="android:paddingRight">3dip</item> + <item name="android:paddingBottom">3dip</item> </style> <style name="Widget.ActionButton"> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 3348b4e..f9e20f7 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -118,6 +118,7 @@ <item name="windowActionBar">false</item> <item name="windowActionModeOverlay">false</item> <item name="windowActionBarStyle">@android:style/ActionBar</item> + <item name="windowActionBarSize">50dip</item> <!-- Dialog attributes --> <item name="alertDialogStyle">@android:style/AlertDialog</item> diff --git a/docs/html/resources/community-groups.jd b/docs/html/resources/community-groups.jd index 6d59648..599c4ae 100644 --- a/docs/html/resources/community-groups.jd +++ b/docs/html/resources/community-groups.jd @@ -87,27 +87,27 @@ phrasing your questions, read <a href="http://www.catb.org/%7Eesr/faqs/smart-que <h3 id="ApplicationDeveloperLists">Application developer mailing lists</h3> <ul> <li><strong><a href="http://groups.google.com/group/android-developers">android-developers</a></strong> -(<a href="mailto:android-developers-subscribe@googlegroups.com">subscribe via email</a>)<br> +(<a href="http://groups.google.com/group/android-developers/subscribe">subscribe</a>)<br> You're now an experienced Android application developer. You've grasped the basics of Android app development, you're comfortable using the SDK, now you want to move to advanced topics. Get help here with troubleshooting applications, advice on implementation, and strategies for improving your application's performance and user experience. This is the not the right place to discuss user issues (use android-discuss for that) or beginner questions with the Android SDK (use android-beginners for that). </li> <li><strong><a href="http://groups.google.com/group/android-discuss">android-discuss</a></strong> -(<a href="mailto:android-discuss-subscribe@googlegroups.com">subscribe via email</a>)<br> +(<a href="http://groups.google.com/group/android-discuss/subscribe">subscribe</a>)<br> The "water cooler" of Android discussion. You can discuss just about anything Android-related here, ideas for the Android platform, announcements about your applications, discussions about Android devices, community resources... As long as your discussion is related to Android, it's on-topic here. However, if you have a discussion here that could belong on another list, you are probably not reaching all of your target audience here and may want to consider shifting to a more targeted list. </li> <li><strong><a href="http://groups.google.com/group/android-ndk">android-ndk</a></strong> -(<a href="mailto:android-ndk-subscribe@googlegroups.com">subscribe via email</a>)<br> +(<a href="http://groups.google.com/group/android-ndk/subscribe">subscribe</a>)<br> A place for discussing the Android NDK and topics related to using native code in Android applications. </li> <li><strong><a href="http://groups.google.com/group/android-security-discuss">android-security-discuss</a></strong> -(<a href="mailto:android-security-discuss-subscribe@googlegroups.com">subscribe via email</a>)<br> +(<a href="http://groups.google.com/group/android-security-discuss/subscribe">subscribe</a>)<br> A place for open discussion on secure development, emerging security concerns, and best practices for and by android developers. Please don't disclose vulnerabilities directly on this list, you'd be putting all Android users at risk. </li> <li><strong><a href="http://groups.google.com/group/android-security-announce">android-security-announce</a></strong> -(<a href="mailto:android-security-announce-subscribe@googlegroups.com">subscribe via email</a>)<br> +(<a href="http://groups.google.com/group/android-security-announce/subscribe">subscribe</a>)<br> A low-volume group for security-related announcements by the Android Security Team. </li> </ul> diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index 4c92942..4ba679b 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -22,6 +22,12 @@ package android.graphics; */ public class BitmapShader extends Shader { /** + * Prevent garbage collection. + */ + @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) + private final Bitmap mBitmap; + + /** * Call this to create a new shader that will draw with a bitmap. * * @param bitmap The bitmap to use inside the shader @@ -29,6 +35,7 @@ public class BitmapShader extends Shader { * @param tileY The tiling mode for y to draw the bitmap in. */ public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) { + mBitmap = bitmap; final int b = bitmap.ni(); native_instance = nativeCreate(b, tileX.nativeInt, tileY.nativeInt); native_shader = nativePostCreate(native_instance, b, tileX.nativeInt, tileY.nativeInt); diff --git a/graphics/java/android/renderscript/Float2.java b/graphics/java/android/renderscript/Float2.java index 8fea91f..889bf7b 100644 --- a/graphics/java/android/renderscript/Float2.java +++ b/graphics/java/android/renderscript/Float2.java @@ -28,6 +28,11 @@ public class Float2 { public Float2() { } + public Float2(float initX, float initY) { + x = initX; + y = initY; + } + public float x; public float y; } diff --git a/graphics/java/android/renderscript/Float3.java b/graphics/java/android/renderscript/Float3.java index 9d9e406..ebe140d 100644 --- a/graphics/java/android/renderscript/Float3.java +++ b/graphics/java/android/renderscript/Float3.java @@ -27,6 +27,11 @@ import android.util.Log; public class Float3 { public Float3() { } + public Float3(float initX, float initY, float initZ) { + x = initX; + y = initY; + z = initZ; + } public float x; public float y; diff --git a/graphics/java/android/renderscript/Float4.java b/graphics/java/android/renderscript/Float4.java index a703e80..847732f 100644 --- a/graphics/java/android/renderscript/Float4.java +++ b/graphics/java/android/renderscript/Float4.java @@ -28,6 +28,13 @@ public class Float4 { public Float4() { } + public Float4(float initX, float initY, float initZ, float initW) { + x = initX; + y = initY; + z = initZ; + w = initW; + } + public float x; public float y; public float z; diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 0c31ba9..74d50e4 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -30,86 +30,106 @@ namespace android { namespace uirenderer { void Matrix4::loadIdentity() { - data[0] = 1.0f; - data[1] = 0.0f; - data[2] = 0.0f; - data[3] = 0.0f; - - data[4] = 0.0f; - data[5] = 1.0f; - data[6] = 0.0f; - data[7] = 0.0f; - - data[8] = 0.0f; - data[9] = 0.0f; - data[10] = 1.0f; - data[11] = 0.0f; - - data[12] = 0.0f; - data[13] = 0.0f; - data[14] = 0.0f; - data[15] = 1.0f; + data[kScaleX] = 1.0f; + data[kSkewY] = 0.0f; + data[2] = 0.0f; + data[kPerspective0] = 0.0f; + + data[kSkewX] = 0.0f; + data[kScaleY] = 1.0f; + data[6] = 0.0f; + data[kPerspective1] = 0.0f; + + data[8] = 0.0f; + data[9] = 0.0f; + data[kScaleZ] = 1.0f; + data[11] = 0.0f; + + data[kTranslateX] = 0.0f; + data[kTranslateY] = 0.0f; + data[kTranslateZ] = 0.0f; + data[kPerspective2] = 1.0f; + + mSimpleMatrix = true; } void Matrix4::load(const float* v) { memcpy(data, v, sizeof(data)); + mSimpleMatrix = false; } void Matrix4::load(const Matrix4& v) { memcpy(data, v.data, sizeof(data)); + mSimpleMatrix = v.mSimpleMatrix; } void Matrix4::load(const SkMatrix& v) { memset(data, 0, sizeof(data)); - data[0] = v[SkMatrix::kMScaleX]; - data[4] = v[SkMatrix::kMSkewX]; - data[12] = v[SkMatrix::kMTransX]; + data[kScaleX] = v[SkMatrix::kMScaleX]; + data[kSkewX] = v[SkMatrix::kMSkewX]; + data[kTranslateX] = v[SkMatrix::kMTransX]; - data[1] = v[SkMatrix::kMSkewY]; - data[5] = v[SkMatrix::kMScaleY]; - data[13] = v[SkMatrix::kMTransY]; + data[kSkewY] = v[SkMatrix::kMSkewY]; + data[kScaleY] = v[SkMatrix::kMScaleY]; + data[kTranslateY] = v[SkMatrix::kMTransY]; - data[3] = v[SkMatrix::kMPersp0]; - data[7] = v[SkMatrix::kMPersp1]; - data[15] = v[SkMatrix::kMPersp2]; + data[kPerspective0] = v[SkMatrix::kMPersp0]; + data[kPerspective1] = v[SkMatrix::kMPersp1]; + data[kPerspective2] = v[SkMatrix::kMPersp2]; - data[10] = 1.0f; + data[kScaleZ] = 1.0f; + + mSimpleMatrix = (v.getType() <= SkMatrix::kScale_Mask); } void Matrix4::copyTo(SkMatrix& v) const { v.reset(); - v.set(SkMatrix::kMScaleX, data[0]); - v.set(SkMatrix::kMSkewX, data[4]); - v.set(SkMatrix::kMTransX, data[12]); + v.set(SkMatrix::kMScaleX, data[kScaleX]); + v.set(SkMatrix::kMSkewX, data[kSkewX]); + v.set(SkMatrix::kMTransX, data[kTranslateX]); - v.set(SkMatrix::kMSkewY, data[1]); - v.set(SkMatrix::kMScaleY, data[5]); - v.set(SkMatrix::kMTransY, data[13]); + v.set(SkMatrix::kMSkewY, data[kSkewY]); + v.set(SkMatrix::kMScaleY, data[kScaleY]); + v.set(SkMatrix::kMTransY, data[kTranslateY]); - v.set(SkMatrix::kMPersp0, data[3]); - v.set(SkMatrix::kMPersp1, data[7]); - v.set(SkMatrix::kMPersp2, data[15]); + v.set(SkMatrix::kMPersp0, data[kPerspective0]); + v.set(SkMatrix::kMPersp1, data[kPerspective1]); + v.set(SkMatrix::kMPersp2, data[kPerspective2]); } void Matrix4::loadInverse(const Matrix4& v) { double scale = 1.0 / - (v.data[0] * ((double) v.data[5] * v.data[15] - (double) v.data[13] * v.data[7]) + - v.data[4] * ((double) v.data[13] * v.data[3] - (double) v.data[1] * v.data[15]) + - v.data[12] * ((double) v.data[1] * v.data[7] - (double) v.data[5] * v.data[3])); - - data[0] = (v.data[5] * v.data[15] - v.data[13] * v.data[7]) * scale; - data[4] = (v.data[12] * v.data[7] - v.data[4] * v.data[15]) * scale; - data[12] = (v.data[4] * v.data[13] - v.data[12] * v.data[5]) * scale; - - data[1] = (v.data[13] * v.data[3] - v.data[1] * v.data[15]) * scale; - data[5] = (v.data[0] * v.data[15] - v.data[12] * v.data[3]) * scale; - data[13] = (v.data[12] * v.data[1] - v.data[0] * v.data[13]) * scale; - - data[3] = (v.data[1] * v.data[7] - v.data[5] * v.data[3]) * scale; - data[7] = (v.data[4] * v.data[3] - v.data[0] * v.data[7]) * scale; - data[15] = (v.data[0] * v.data[5] - v.data[4] * v.data[1]) * scale; + (v.data[kScaleX] * ((double) v.data[kScaleY] * v.data[kPerspective2] - + (double) v.data[kTranslateY] * v.data[kPerspective1]) + + v.data[kSkewX] * ((double) v.data[kTranslateY] * v.data[kPerspective0] - + (double) v.data[kSkewY] * v.data[kPerspective2]) + + v.data[kTranslateX] * ((double) v.data[kSkewY] * v.data[kPerspective1] - + (double) v.data[kScaleY] * v.data[kPerspective0])); + + data[kScaleX] = (v.data[kScaleY] * v.data[kPerspective2] - + v.data[kTranslateY] * v.data[kPerspective1]) * scale; + data[kSkewX] = (v.data[kTranslateX] * v.data[kPerspective1] - + v.data[kSkewX] * v.data[kPerspective2]) * scale; + data[kTranslateX] = (v.data[kSkewX] * v.data[kTranslateY] - + v.data[kTranslateX] * v.data[kScaleY]) * scale; + + data[kSkewY] = (v.data[kTranslateY] * v.data[kPerspective0] - + v.data[kSkewY] * v.data[kPerspective2]) * scale; + data[kScaleY] = (v.data[kScaleX] * v.data[kPerspective2] - + v.data[kTranslateX] * v.data[kPerspective0]) * scale; + data[kTranslateY] = (v.data[kTranslateX] * v.data[kSkewY] - + v.data[kScaleX] * v.data[kTranslateY]) * scale; + + data[kPerspective0] = (v.data[kSkewY] * v.data[kPerspective1] - + v.data[kScaleY] * v.data[kPerspective0]) * scale; + data[kPerspective1] = (v.data[kSkewX] * v.data[kPerspective0] - + v.data[kScaleX] * v.data[kPerspective1]) * scale; + data[kPerspective2] = (v.data[kScaleX] * v.data[kScaleY] - + v.data[kSkewX] * v.data[kSkewY]) * scale; + + mSimpleMatrix = v.mSimpleMatrix; } void Matrix4::copyTo(float* v) const { @@ -117,35 +137,35 @@ void Matrix4::copyTo(float* v) const { } float Matrix4::getTranslateX() { - return data[12]; + return data[kTranslateX]; } float Matrix4::getTranslateY() { - return data[13]; + return data[kTranslateY]; } void Matrix4::loadTranslate(float x, float y, float z) { loadIdentity(); - data[12] = x; - data[13] = y; - data[14] = z; + data[kTranslateX] = x; + data[kTranslateY] = y; + data[kTranslateZ] = z; } void Matrix4::loadScale(float sx, float sy, float sz) { loadIdentity(); - data[0] = sx; - data[5] = sy; - data[10] = sz; + data[kScaleX] = sx; + data[kScaleY] = sy; + data[kScaleZ] = sz; } void Matrix4::loadRotate(float angle, float x, float y, float z) { - data[3] = 0.0f; - data[7] = 0.0f; - data[11] = 0.0f; - data[12] = 0.0f; - data[13] = 0.0f; - data[14] = 0.0f; - data[15] = 1.0f; + data[kPerspective0] = 0.0f; + data[kPerspective1] = 0.0f; + data[11] = 0.0f; + data[kTranslateX] = 0.0f; + data[kTranslateY] = 0.0f; + data[kTranslateZ] = 0.0f; + data[kPerspective2] = 1.0f; angle *= float(M_PI / 180.0f); float c = cosf(angle); @@ -165,15 +185,17 @@ void Matrix4::loadRotate(float angle, float x, float y, float z) { const float ys = y * s; const float zs = z * s; - data[0] = x * x * nc + c; - data[4] = xy * nc - zs; - data[8] = zx * nc + ys; - data[1] = xy * nc + zs; - data[5] = y * y * nc + c; - data[9] = yz * nc - xs; - data[2] = zx * nc - ys; - data[6] = yz * nc + xs; - data[10] = z * z * nc + c; + data[kScaleX] = x * x * nc + c; + data[kSkewX] = xy * nc - zs; + data[8] = zx * nc + ys; + data[kSkewY] = xy * nc + zs; + data[kScaleY] = y * y * nc + c; + data[9] = yz * nc - xs; + data[2] = zx * nc - ys; + data[6] = yz * nc + xs; + data[kScaleZ] = z * z * nc + c; + + mSimpleMatrix = false; } void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) { @@ -196,39 +218,89 @@ void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) { set(i, 2, z); set(i, 3, w); } + + mSimpleMatrix = u.mSimpleMatrix && v.mSimpleMatrix; } void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) { loadIdentity(); - data[0] = 2.0f / (right - left); - data[5] = 2.0f / (top - bottom); - data[10] = -2.0f / (far - near); - data[12] = -(right + left) / (right - left); - data[13] = -(top + bottom) / (top - bottom); - data[14] = -(far + near) / (far - near); + data[kScaleX] = 2.0f / (right - left); + data[kScaleY] = 2.0f / (top - bottom); + data[kScaleZ] = -2.0f / (far - near); + data[kTranslateX] = -(right + left) / (right - left); + data[kTranslateY] = -(top + bottom) / (top - bottom); + data[kTranslateZ] = -(far + near) / (far - near); } #define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c) +void Matrix4::mapPoint(float& x, float& y) const { + if (mSimpleMatrix) { + MUL_ADD_STORE(x, data[kScaleX], data[kTranslateX]); + MUL_ADD_STORE(y, data[kScaleY], data[kTranslateY]); + return; + } + + float dx = x * data[kScaleX] + y * data[kSkewX] + data[kTranslateX]; + float dy = x * data[kSkewY] + y * data[kScaleY] + data[kTranslateY]; + float dz = x * data[kPerspective0] + y * data[kPerspective1] + data[kPerspective2]; + if (dz) dz = 1.0f / dz; + + x = dx * dz; + y = dy * dz; +} + void Matrix4::mapRect(Rect& r) const { - const float sx = data[0]; - const float sy = data[5]; + if (mSimpleMatrix) { + MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]); + MUL_ADD_STORE(r.right, data[kScaleX], data[kTranslateX]); + MUL_ADD_STORE(r.top, data[kScaleY], data[kTranslateY]); + MUL_ADD_STORE(r.bottom, data[kScaleY], data[kTranslateY]); + return; + } + + float vertices[] = { + r.left, r.top, + r.right, r.top, + r.right, r.bottom, + r.left, r.bottom + }; + + float x, y, z; + + for (int i = 0; i < 8; i+= 2) { + float px = vertices[i]; + float py = vertices[i + 1]; - const float tx = data[12]; - const float ty = data[13]; + x = px * data[kScaleX] + py * data[kSkewX] + data[kTranslateX]; + y = px * data[kSkewY] + py * data[kScaleY] + data[kTranslateY]; + z = px * data[kPerspective0] + py * data[kPerspective1] + data[kPerspective2]; + if (z) z = 1.0f / z; - MUL_ADD_STORE(r.left, sx, tx); - MUL_ADD_STORE(r.right, sx, tx); - MUL_ADD_STORE(r.top, sy, ty); - MUL_ADD_STORE(r.bottom, sy, ty); + vertices[i] = x * z; + vertices[i + 1] = y * z; + } + + r.left = r.right = vertices[0]; + r.top = r.bottom = vertices[1]; + + for (int i = 2; i < 8; i += 2) { + x = vertices[i]; + y = vertices[i + 1]; + + if (x < r.left) r.left = x; + else if (x > r.right) r.right = x; + if (y < r.top) r.top = y; + else if (y > r.bottom) r.bottom = y; + } } void Matrix4::dump() const { - LOGD("Matrix4["); - LOGD(" %f %f %f %f", data[0], data[4], data[ 8], data[12]); - LOGD(" %f %f %f %f", data[1], data[5], data[ 9], data[13]); - LOGD(" %f %f %f %f", data[2], data[6], data[10], data[14]); - LOGD(" %f %f %f %f", data[3], data[7], data[11], data[15]); + LOGD("Matrix4[simple=%d", mSimpleMatrix); + LOGD(" %f %f %f %f", data[kScaleX], data[kSkewX], data[ 8], data[kTranslateX]); + LOGD(" %f %f %f %f", data[kSkewY], data[kScaleY], data[ 9], data[kTranslateY]); + LOGD(" %f %f %f %f", data[2], data[6], data[kScaleZ], data[kTranslateZ]); + LOGD(" %f %f %f %f", data[kPerspective0], data[kPerspective1], data[11], data[kPerspective2]); LOGD("]"); } diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index b8a4da7..c247a67 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -32,6 +32,20 @@ class Matrix4 { public: float data[16]; + enum Entry { + kScaleX = 0, + kSkewY = 1, + kPerspective0 = 3, + kSkewX = 4, + kScaleY = 5, + kPerspective1 = 7, + kScaleZ = 10, + kTranslateX = 12, + kTranslateY = 13, + kTranslateZ = 14, + kPerspective2 = 15 + }; + Matrix4() { loadIdentity(); } @@ -90,10 +104,8 @@ public: void copyTo(float* v) const; void copyTo(SkMatrix& v) const; - /** - * Does not apply rotations! - */ void mapRect(Rect& r) const; + void mapPoint(float& x, float& y) const; float getTranslateX(); float getTranslateY(); @@ -101,6 +113,8 @@ public: void dump() const; private: + bool mSimpleMatrix; + inline float get(int i, int j) const { return data[i * 4 + j]; } diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 3569d6a..c7a01b1 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -164,7 +164,8 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV Rect start(mBounds[0], mBounds[1], mBounds[2], mBounds[3]); if (mMatrix) { mat4 shaderMatrix(*mMatrix); - shaderMatrix.mapRect(start); + shaderMatrix.mapPoint(start.left, start.top); + shaderMatrix.mapPoint(start.right, start.bottom); } snapshot.transform.mapRect(start); diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index 342e5b1..9495bee 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -96,14 +96,9 @@ public: bool clip(float left, float top, float right, float bottom, SkRegion::Op op) { bool clipped = false; - SkRect sr; - sr.set(left, top, right, bottom); + Rect r(left, top, right, bottom); + transform.mapRect(r); - SkMatrix m; - transform.copyTo(m); - m.mapRect(&sr); - - Rect r(sr.fLeft, sr.fTop, sr.fRight, sr.fBottom); switch (op) { case SkRegion::kDifference_Op: break; @@ -143,14 +138,8 @@ public: mat4 inverse; inverse.loadInverse(transform); - SkRect sr; - sr.set(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); - - SkMatrix m; - inverse.copyTo(m); - m.mapRect(&sr); - - localClip.set(sr.fLeft, sr.fTop, sr.fRight, sr.fBottom); + localClip.set(clipRect); + inverse.mapRect(localClip); flags &= ~Snapshot::kFlagDirtyLocalClip; } diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs index 4ed5aba..58c9acf 100644 --- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs +++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/horizontal_blur.rs @@ -8,43 +8,23 @@ void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32 const uchar4 *input = (const uchar4 *)rsGetElementAt(fs->ain, 0, y); float3 blurredPixel = 0; - float3 currentPixel = 0; - const float *gPtr = fs->gaussian; if ((x > fs->radius) && (x < (fs->width - fs->radius))) { const uchar4 *i = input + (x - fs->radius); for(int r = -fs->radius; r <= fs->radius; r ++) { - currentPixel.x = (float)(i->x); - currentPixel.y = (float)(i->y); - currentPixel.z = (float)(i->z); - blurredPixel += currentPixel * gPtr[0]; + blurredPixel += convert_float3(i->xyz) * gPtr[0]; gPtr++; i++; } } else { for(int r = -fs->radius; r <= fs->radius; r ++) { // Stepping left and right away from the pixel - int validW = x + r; - // Clamp to zero and width max() isn't exposed for ints yet - if(validW < 0) { - validW = 0; - } - if(validW > fs->width - 1) { - validW = fs->width - 1; - } - //int validW = rsClamp(w + r, 0, width - 1); - - currentPixel.x = (float)(input[validW].x); - currentPixel.y = (float)(input[validW].y); - currentPixel.z = (float)(input[validW].z); - - blurredPixel += currentPixel * gPtr[0]; + int validW = rsClamp(x + r, (uint)0, (uint)(fs->width - 1)); + blurredPixel += convert_float3(input[validW].xyz) * gPtr[0]; gPtr++; } } - output->x = (uint8_t)blurredPixel.x; - output->y = (uint8_t)blurredPixel.y; - output->z = (uint8_t)blurredPixel.z; + output->xyz = convert_uchar3(blurredPixel); } diff --git a/libs/rs/java/SceneGraph/Android.mk b/libs/rs/java/SceneGraph/Android.mk new file mode 100644 index 0000000..5520446 --- /dev/null +++ b/libs/rs/java/SceneGraph/Android.mk @@ -0,0 +1,31 @@ +# +# 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. +# + +ifneq ($(TARGET_SIMULATOR),true) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) +#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript + +LOCAL_PACKAGE_NAME := SceneGraph + +include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/SceneGraph/AndroidManifest.xml b/libs/rs/java/SceneGraph/AndroidManifest.xml new file mode 100644 index 0000000..8a8f87a --- /dev/null +++ b/libs/rs/java/SceneGraph/AndroidManifest.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.scenegraph"> + <application android:label="SceneGraph"> + <activity android:name="SceneGraph" + android:theme="@android:style/Theme.Black.NoTitleBar"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/libs/rs/java/SceneGraph/res/drawable/robot.png b/libs/rs/java/SceneGraph/res/drawable/robot.png Binary files differnew file mode 100644 index 0000000..f7353fd --- /dev/null +++ b/libs/rs/java/SceneGraph/res/drawable/robot.png diff --git a/libs/rs/java/SceneGraph/res/raw/robot.a3d b/libs/rs/java/SceneGraph/res/raw/robot.a3d Binary files differnew file mode 100644 index 0000000..2d7d32b --- /dev/null +++ b/libs/rs/java/SceneGraph/res/raw/robot.a3d diff --git a/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraph.java b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraph.java new file mode 100644 index 0000000..5daa4ac --- /dev/null +++ b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraph.java @@ -0,0 +1,71 @@ +/* + * 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 com.android.scenegraph; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class SceneGraph extends Activity { + + private SceneGraphView mView; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new SceneGraphView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.onResume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.onPause(); + } + +} + diff --git a/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraphRS.java b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraphRS.java new file mode 100644 index 0000000..3db4a2b --- /dev/null +++ b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraphRS.java @@ -0,0 +1,220 @@ +/* + * 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 com.android.scenegraph; + +import java.io.Writer; +import java.util.Map; +import java.util.Vector; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.Element.Builder; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + + +public class SceneGraphRS { + + private final int STATE_LAST_FOCUS = 1; + + int mWidth; + int mHeight; + int mRotation; + + public SceneGraphRS() { + } + + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + mWidth = width; + mHeight = height; + mRotation = 0; + initRS(); + } + + private Resources mRes; + private RenderScriptGL mRS; + private Sampler mSampler; + private ProgramStore mPSBackground; + private ProgramFragment mPFBackground; + private ProgramVertex mPVBackground; + private ProgramVertex.MatrixAllocation mPVA; + + private Allocation mGridImage; + private Allocation mAllocPV; + + private Mesh mMesh; + + private Font mItalic; + private Allocation mTextAlloc; + + private ScriptC_Scenegraph mScript; + private ScriptC_Transform mTransformScript; + + int mLastX; + int mLastY; + + public void touchEvent(int x, int y) { + int dx = mLastX - x; + if(Math.abs(dx) > 50 || Math.abs(dx) < 3) { + dx = 0; + } + + mRotation -= dx; + if(mRotation > 360) { + mRotation -= 360; + } + if(mRotation < 0) { + mRotation += 360; + } + + mScript.set_gRotate(-(float)mRotation); + + mLastX = x; + mLastY = y; + } + + private void initPFS() { + ProgramStore.Builder b = new ProgramStore.Builder(mRS, null, null); + + b.setDepthFunc(ProgramStore.DepthFunc.LESS); + b.setDitherEnable(false); + b.setDepthMask(true); + mPSBackground = b.create(); + + mScript.set_gPFSBackground(mPSBackground); + } + + private void initPF() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMin(Sampler.Value.LINEAR); + bs.setMag(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.CLAMP); + bs.setWrapT(Sampler.Value.WRAP); + mSampler = bs.create(); + + ProgramFragment.Builder b = new ProgramFragment.Builder(mRS); + b.setTexture(ProgramFragment.Builder.EnvMode.REPLACE, + ProgramFragment.Builder.Format.RGBA, 0); + mPFBackground = b.create(); + mPFBackground.bindSampler(mSampler, 0); + + mScript.set_gPFBackground(mPFBackground); + } + + private void initPV() { + ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null); + mPVBackground = pvb.create(); + + mPVA = new ProgramVertex.MatrixAllocation(mRS); + mPVBackground.bindAllocation(mPVA); + mPVA.setupProjectionNormalized(mWidth, mHeight); + + mScript.set_gPVBackground(mPVBackground); + } + + private void loadImage() { + mGridImage = Allocation.createFromBitmapResourceBoxed(mRS, mRes, R.drawable.robot, Element.RGB_565(mRS), true); + mGridImage.uploadToTexture(0); + + mScript.set_gTGrid(mGridImage); + } + + private void initTextAllocation() { + String allocString = "Displaying file: R.raw.robot"; + mTextAlloc = Allocation.createFromString(mRS, allocString); + mScript.set_gTextAlloc(mTextAlloc); + } + + SgTransform mRootTransform; + SgTransform mGroup1; + + SgTransform mRobot1; + SgTransform mRobot2; + + void initTransformHierarchy() { + mRootTransform = new SgTransform(mRS); + + mGroup1 = new SgTransform(mRS); + mRootTransform.addChild(mGroup1); + + mRobot1 = new SgTransform(mRS); + mRobot2 = new SgTransform(mRS); + + mGroup1.addChild(mRobot1); + mGroup1.addChild(mRobot2); + + mGroup1.setTransform(0, new Float4(0.0f, 0.0f, 5.0f, 0.0f), TransformType.TRANSLATE); + mGroup1.setTransform(1, new Float4(0.0f, 1.0f, 0.0f, 15.0f), TransformType.ROTATE); + + mRobot1.setTransform(0, new Float4(-2.0f, -0.5f, 0.0f, 0.0f), TransformType.TRANSLATE); + mRobot1.setTransform(1, new Float4(0.0f, 1.0f, 0.0f, 20.0f), TransformType.ROTATE); + mRobot1.setTransform(2, new Float4(0.2f, 0.2f, 0.2f, 0.0f), TransformType.SCALE); + + mRobot2.setTransform(0, new Float4(2.0f, 0.0f, 0.0f, 0.0f), TransformType.TRANSLATE); + mRobot2.setTransform(1, new Float4(0.0f, 1.0f, 0.0f, -20.0f), TransformType.ROTATE); + mRobot2.setTransform(2, new Float4(0.3f, 0.3f, 0.3f, 0.0f), TransformType.SCALE); + } + + private void initRS() { + + mScript = new ScriptC_Scenegraph(mRS, mRes, R.raw.scenegraph, true); + mTransformScript = new ScriptC_Transform(mRS, mRes, R.raw.transform, false); + mTransformScript.set_transformScript(mTransformScript); + + mScript.set_gTransformRS(mTransformScript); + + initPFS(); + initPF(); + initPV(); + + loadImage(); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot); + FileA3D.IndexEntry entry = model.getIndexEntry(0); + if(entry == null || entry.getClassID() != FileA3D.ClassID.MESH) { + Log.e("rs", "could not load model"); + } + else { + mMesh = (Mesh)entry.getObject(); + mScript.set_gTestMesh(mMesh); + } + + mItalic = Font.create(mRS, mRes, "DroidSerif-Italic.ttf", 8); + mScript.set_gItalic(mItalic); + + initTextAllocation(); + + initTransformHierarchy(); + + Log.v("========SceneGraph========", "transform hierarchy initialized"); + + mScript.bind_gRootNode(mRootTransform.getField()); + + mScript.bind_gGroup(mGroup1.mParent.mChildField); + mScript.bind_gRobot1(mRobot1.mParent.mChildField); + mScript.set_gRobot1Index(mRobot1.mIndexInParentGroup); + mScript.bind_gRobot2(mRobot2.mParent.mChildField); + mScript.set_gRobot2Index(mRobot2.mIndexInParentGroup); + + mRS.contextBindRootScript(mScript); + } +} + + + diff --git a/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraphView.java b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraphView.java new file mode 100644 index 0000000..ae94869 --- /dev/null +++ b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SceneGraphView.java @@ -0,0 +1,94 @@ +/* + * 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 com.android.scenegraph; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class SceneGraphView extends RSSurfaceView { + + public SceneGraphView(Context context) { + super(context); + //setFocusable(true); + } + + private RenderScriptGL mRS; + private SceneGraphRS mRender; + + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + mRS = createRenderScript(true); + mRS.contextSetSurface(w, h, holder.getSurface()); + mRender = new SceneGraphRS(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if(mRS != null) { + mRS = null; + destroyRenderScript(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + // break point at here + // this method doesn't work when 'extends View' include 'extends ScrollView'. + return super.onKeyDown(keyCode, event); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) + { + boolean ret = true; + int act = ev.getAction(); + if (act == ev.ACTION_UP) { + ret = false; + } + + mRender.touchEvent((int)ev.getX(), (int)ev.getY()); + return ret; + } +} + + diff --git a/libs/rs/java/SceneGraph/src/com/android/scenegraph/SgTransform.java b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SgTransform.java new file mode 100644 index 0000000..e81f1a7 --- /dev/null +++ b/libs/rs/java/SceneGraph/src/com/android/scenegraph/SgTransform.java @@ -0,0 +1,165 @@ +/* + * 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 com.android.scenegraph; + +import java.io.Writer; +import java.util.Map; +import java.util.Vector; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.Element.Builder; +import android.renderscript.ProgramStore.DepthFunc; +import android.util.Log; + +enum TransformType { + + NONE(0), + TRANSLATE(1), + ROTATE(2), + SCALE(3); + + int mID; + TransformType(int id) { + mID = id; + } +} + +public class SgTransform { + + + ScriptField_SgTransform mTransformField; + ScriptField_SgTransform mChildField; + public ScriptField_SgTransform.Item mTransformData; + + Float4[] mTransforms; + TransformType[] mTransformTypes; + + RenderScript mRS; + + Vector mChildren; + SgTransform mParent; + int mIndexInParentGroup; + + public void setParent(SgTransform parent, int parentIndex) { + mParent = parent; + mIndexInParentGroup = parentIndex; + } + + public void addChild(SgTransform child) { + mChildren.add(child); + child.setParent(this, mChildren.size() - 1); + } + + public void setTransform(int index, Float4 value, TransformType type) { + mTransforms[index] = value; + mTransformTypes[index] = type; + } + + void initData() { + int numTransforms = 16; + mTransforms = new Float4[numTransforms]; + mTransformTypes = new TransformType[numTransforms]; + for(int i = 0; i < numTransforms; i ++) { + mTransforms[i] = new Float4(0, 0, 0, 0); + mTransformTypes[i] = TransformType.NONE; + } + } + + void setData() { + + mTransformData.globalMat_Row0 = new Float4(1, 0, 0, 0); + mTransformData.globalMat_Row1 = new Float4(0, 1, 0, 0); + mTransformData.globalMat_Row2 = new Float4(0, 0, 1, 0); + mTransformData.globalMat_Row3 = new Float4(0, 0, 0, 1); + + mTransformData.localMat_Row0 = new Float4(1, 0, 0, 0); + mTransformData.localMat_Row1 = new Float4(0, 1, 0, 0); + mTransformData.localMat_Row2 = new Float4(0, 0, 1, 0); + mTransformData.localMat_Row3 = new Float4(0, 0, 0, 1); + + mTransformData.transforms0 = mTransforms[0]; + mTransformData.transforms1 = mTransforms[1]; + mTransformData.transforms2 = mTransforms[2]; + mTransformData.transforms3 = mTransforms[3]; + mTransformData.transforms4 = mTransforms[4]; + mTransformData.transforms5 = mTransforms[5]; + mTransformData.transforms6 = mTransforms[6]; + mTransformData.transforms7 = mTransforms[7]; + mTransformData.transforms8 = mTransforms[8]; + mTransformData.transforms9 = mTransforms[9]; + mTransformData.transforms10 = mTransforms[10]; + mTransformData.transforms11 = mTransforms[11]; + mTransformData.transforms12 = mTransforms[12]; + mTransformData.transforms13 = mTransforms[13]; + mTransformData.transforms14 = mTransforms[14]; + mTransformData.transforms15 = mTransforms[15]; + + mTransformData.transformType0 = mTransformTypes[0].mID; + mTransformData.transformType1 = mTransformTypes[1].mID; + mTransformData.transformType2 = mTransformTypes[2].mID; + mTransformData.transformType3 = mTransformTypes[3].mID; + mTransformData.transformType4 = mTransformTypes[4].mID; + mTransformData.transformType5 = mTransformTypes[5].mID; + mTransformData.transformType6 = mTransformTypes[6].mID; + mTransformData.transformType7 = mTransformTypes[7].mID; + mTransformData.transformType8 = mTransformTypes[8].mID; + mTransformData.transformType9 = mTransformTypes[9].mID; + mTransformData.transformType10 = mTransformTypes[10].mID; + mTransformData.transformType11 = mTransformTypes[11].mID; + mTransformData.transformType12 = mTransformTypes[12].mID; + mTransformData.transformType13 = mTransformTypes[13].mID; + mTransformData.transformType14 = mTransformTypes[14].mID; + mTransformData.transformType15 = mTransformTypes[15].mID; + + mTransformData.isDirty = 1; + mTransformData.children = null; + + } + + public SgTransform(RenderScript rs) { + mRS = rs; + mTransformData = new ScriptField_SgTransform.Item(); + mChildren = new Vector(); + initData(); + } + + public ScriptField_SgTransform.Item getData() { + setData(); + if(mChildren.size() != 0) { + mChildField = new ScriptField_SgTransform(mRS, mChildren.size()); + mTransformData.children = mChildField.getAllocation(); + + for(int i = 0; i < mChildren.size(); i ++) { + SgTransform child = (SgTransform)mChildren.get(i); + mChildField.set(child.getData(), i, false); + } + mChildField.copyAll(); + } + + return mTransformData; + } + + public ScriptField_SgTransform getField() { + mTransformField = new ScriptField_SgTransform(mRS, 1); + mTransformField.set(getData(), 0, true); + return mTransformField; + } +} + + + diff --git a/libs/rs/java/SceneGraph/src/com/android/scenegraph/scenegraph.rs b/libs/rs/java/SceneGraph/src/com/android/scenegraph/scenegraph.rs new file mode 100644 index 0000000..e6ae6df --- /dev/null +++ b/libs/rs/java/SceneGraph/src/com/android/scenegraph/scenegraph.rs @@ -0,0 +1,92 @@ +// Copyright (C) 2009 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +#include "rs_graphics.rsh" +#include "transform_def.rsh" + +rs_program_vertex gPVBackground; +rs_program_fragment gPFBackground; + +rs_allocation gTGrid; +rs_mesh gTestMesh; + +rs_program_store gPFSBackground; + +float gRotate; + +rs_font gItalic; +rs_allocation gTextAlloc; + +rs_script gTransformRS; + +SgTransform *gGroup; +SgTransform *gRobot1; +int gRobot1Index; +SgTransform *gRobot2; +int gRobot2Index; + +SgTransform *gRootNode; + +#pragma rs export_var(gPVBackground, gPFBackground, gTGrid, gTestMesh, gPFSBackground, gRotate, gItalic, gTextAlloc, gTransformRS, gGroup, gRobot1, gRobot1Index, gRobot2, gRobot2Index, gRootNode) + +float gDT; +int64_t gLastTime; + +void init() { + gRotate = 0.0f; +} + +int root(int launchID) { + + gGroup->transforms1.w += 0.5f; + gGroup->isDirty = 1; + + SgTransform *robot1Ptr = gRobot1 + gRobot1Index; + + robot1Ptr->transforms1.w -= 1.5f; + robot1Ptr->isDirty = 1; + + SgTransform *robot2Ptr = gRobot2 + gRobot2Index; + robot2Ptr->transforms1.w += 2.5f; + robot2Ptr->isDirty = 1; + + rsForEach(gTransformRS, gRootNode->children, gRootNode->children, 0); + + rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgClearDepth(1.0f); + + rsgBindProgramVertex(gPVBackground); + + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPFSBackground); + rsgBindTexture(gPFBackground, 0, gTGrid); + + rsgProgramVertexLoadModelMatrix((rs_matrix4x4 *)&robot1Ptr->globalMat_Row0); + rsgDrawMesh(gTestMesh); + + rsgProgramVertexLoadModelMatrix((rs_matrix4x4 *)&robot2Ptr->globalMat_Row0); + rsgDrawMesh(gTestMesh); + + color(0.3f, 0.3f, 0.3f, 1.0f); + rsgDrawText("Renderscript transform test", 30, 695); + + rsgBindFont(gItalic); + rsgDrawText(gTextAlloc, 30, 730); + + return 10; +} diff --git a/libs/rs/java/SceneGraph/src/com/android/scenegraph/transform.rs b/libs/rs/java/SceneGraph/src/com/android/scenegraph/transform.rs new file mode 100644 index 0000000..a62d12b --- /dev/null +++ b/libs/rs/java/SceneGraph/src/com/android/scenegraph/transform.rs @@ -0,0 +1,102 @@ +// Copyright (C) 2009 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +#include "transform_def.rsh" + +rs_script transformScript; + +#pragma rs export_var(transformScript) + +typedef struct { + int changed; + rs_matrix4x4 *mat; +} ParentData; + +void appendTransformation(int type, float4 data, rs_matrix4x4 *mat) { + rs_matrix4x4 temp; + + switch(type) { + case TRANSFORM_TRANSLATE: + rsMatrixLoadTranslate(&temp, data.x, data.y, data.z); + break; + case TRANSFORM_ROTATE: + rsMatrixLoadRotate(&temp, data.w, data.x, data.y, data.z); + break; + case TRANSFORM_SCALE: + rsMatrixLoadScale(&temp, data.x, data.y, data.z); + break; + } + rsMatrixMultiply(mat, &temp); +} + +void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) { + + SgTransform *data = (SgTransform *)v_out; + const ParentData *parent = (const ParentData *)usrData; + + //rsDebug("Transform data", (int)data); + //rsDebug("Entering parent", (int)parent); + + rs_matrix4x4 *localMat = (rs_matrix4x4*)&data->localMat_Row0; + rs_matrix4x4 *globalMat = (rs_matrix4x4*)&data->globalMat_Row0; + + ParentData toChild; + toChild.changed = 0; + toChild.mat = globalMat; + + //rsDebug("Transform is dirty", data->isDirty); + + // Refresh matrices if dirty + if(data->isDirty) { + data->isDirty = 0; + toChild.changed = 1; + + // Reset our local matrix + rsMatrixLoadIdentity(localMat); + + float4 *transformSource = &data->transforms0; + int *transformTypes = &data->transformType0; + + for(int i = 0; i < 16; i ++) { + if(transformTypes[i] == TRANSFORM_NONE) { + break; + } + //rsDebug("Transform adding transformation", transformTypes[i]); + appendTransformation(transformTypes[i], transformSource[i], localMat); + } + } + + //rsDebug("Transform checking parent", (int)0); + + if(parent) { + if(parent->changed) { + toChild.changed = 1; + + rsMatrixLoad(globalMat, parent->mat); + rsMatrixMultiply(globalMat, localMat); + } + } + else { + rsMatrixLoad(globalMat, localMat); + } + + //rsDebug("Transform calling self with child ", (int)data->children.p); + if(data->children.p) { + rsForEach(transformScript, data->children, data->children, (void*)&toChild); + } +} diff --git a/libs/rs/java/SceneGraph/src/com/android/scenegraph/transform_def.rsh b/libs/rs/java/SceneGraph/src/com/android/scenegraph/transform_def.rsh new file mode 100644 index 0000000..10aac37 --- /dev/null +++ b/libs/rs/java/SceneGraph/src/com/android/scenegraph/transform_def.rsh @@ -0,0 +1,73 @@ +// Copyright (C) 2009 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. + +#pragma version(1) + +#pragma rs java_package_name(com.android.scenegraph) + +#define TRANSFORM_NONE 0 +#define TRANSFORM_TRANSLATE 1 +#define TRANSFORM_ROTATE 2 +#define TRANSFORM_SCALE 3 + +typedef struct { + float4 globalMat_Row0; + float4 globalMat_Row1; + float4 globalMat_Row2; + float4 globalMat_Row3; + + float4 localMat_Row0; + float4 localMat_Row1; + float4 localMat_Row2; + float4 localMat_Row3; + + float4 transforms0; + float4 transforms1; + float4 transforms2; + float4 transforms3; + float4 transforms4; + float4 transforms5; + float4 transforms6; + float4 transforms7; + float4 transforms8; + float4 transforms9; + float4 transforms10; + float4 transforms11; + float4 transforms12; + float4 transforms13; + float4 transforms14; + float4 transforms15; + + int transformType0; + int transformType1; + int transformType2; + int transformType3; + int transformType4; + int transformType5; + int transformType6; + int transformType7; + int transformType8; + int transformType9; + int transformType10; + int transformType11; + int transformType12; + int transformType13; + int transformType14; + int transformType15; + + int isDirty; + + rs_allocation children; + +} SgTransform; diff --git a/libs/rs/java/tests/Android.mk b/libs/rs/java/tests/Android.mk new file mode 100644 index 0000000..6c992d5 --- /dev/null +++ b/libs/rs/java/tests/Android.mk @@ -0,0 +1,30 @@ +# +# 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. +# + +ifneq ($(TARGET_SIMULATOR),true) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) + +LOCAL_PACKAGE_NAME := RSTest + +include $(BUILD_PACKAGE) + +endif diff --git a/libs/rs/java/tests/AndroidManifest.xml b/libs/rs/java/tests/AndroidManifest.xml new file mode 100644 index 0000000..bc144ab --- /dev/null +++ b/libs/rs/java/tests/AndroidManifest.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.rs.test"> + <application + android:label="_RS_Test" + android:icon="@drawable/test_pattern"> + <activity android:name="RSTest"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/libs/rs/java/tests/res/drawable/test_pattern.png b/libs/rs/java/tests/res/drawable/test_pattern.png Binary files differnew file mode 100644 index 0000000..e7d1455 --- /dev/null +++ b/libs/rs/java/tests/res/drawable/test_pattern.png diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTest.java b/libs/rs/java/tests/src/com/android/rs/test/RSTest.java new file mode 100644 index 0000000..121793d --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/RSTest.java @@ -0,0 +1,85 @@ +/* + * 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 com.android.rs.test; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Config; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; + +import java.lang.Runtime; + +public class RSTest extends Activity { + //EventListener mListener = new EventListener(); + + private static final String LOG_TAG = "libRS_jni"; + private static final boolean DEBUG = false; + private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; + + private RSTestView mView; + + // get the current looper (from your Activity UI thread for instance + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Create our Preview view and set it as the content of our + // Activity + mView = new RSTestView(this); + setContentView(mView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mView.onResume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.onPause(); + } + + static void log(String message) { + if (LOG_ENABLED) { + Log.v(LOG_TAG, message); + } + } + + +} + diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java new file mode 100644 index 0000000..c1a16dd --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java @@ -0,0 +1,72 @@ +/* + * 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 com.android.rs.test; + +import android.content.res.Resources; +import android.renderscript.*; +import android.util.Log; + + +public class RSTestCore { + public static final int PART_COUNT = 50000; + + public RSTestCore() { + } + + private Resources mRes; + private RenderScriptGL mRS; + + private ScriptC_Test_root mRootScript; + + private boolean fp_mad() { + ScriptC_Fp_mad s = new ScriptC_Fp_mad(mRS, mRes, R.raw.fp_mad, true); + s.invoke_doTest(0, 0); + return true; + } + + //private ScriptC_Fountain mScript; + public void init(RenderScriptGL rs, Resources res, int width, int height) { + mRS = rs; + mRes = res; + + mRootScript = new ScriptC_Test_root(mRS, mRes, R.raw.test_root, true); + + fp_mad(); + + + /* + ProgramFragment.Builder pfb = new ProgramFragment.Builder(rs); + pfb.setVaryingColor(true); + rs.contextBindProgramFragment(pfb.create()); + + ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT); + + Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS); + smb.addVertexAllocation(points.getAllocation()); + smb.addIndexType(Primitive.POINT); + Mesh sm = smb.create(); + + mScript = new ScriptC_Fountain(mRS, mRes, R.raw.fountain, true); + mScript.set_partMesh(sm); + mScript.bind_point(points); + mRS.contextBindRootScript(mScript); + */ + } + + public void newTouchPosition(float x, float y, float pressure, int id) { + } +} diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java new file mode 100644 index 0000000..7ae0c08 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java @@ -0,0 +1,106 @@ +/* + * 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 com.android.rs.test; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.KeyEvent; +import android.view.MotionEvent; + +public class RSTestView extends RSSurfaceView { + + public RSTestView(Context context) { + super(context); + //setFocusable(true); + } + + private RenderScriptGL mRS; + private RSTestCore mRender; + + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + if (mRS == null) { + mRS = createRenderScript(false); + mRS.contextSetSurface(w, h, holder.getSurface()); + mRender = new RSTestCore(); + mRender.init(mRS, getResources(), w, h); + } + } + + @Override + protected void onDetachedFromWindow() { + if(mRS != null) { + mRS = null; + destroyRenderScript(); + } + } + +/* + @Override + public boolean onTouchEvent(MotionEvent ev) + { + int act = ev.getActionMasked(); + if (act == ev.ACTION_UP) { + mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0)); + return false; + } else if (act == MotionEvent.ACTION_POINTER_UP) { + // only one pointer going up, we can get the index like this + int pointerIndex = ev.getActionIndex(); + int pointerId = ev.getPointerId(pointerIndex); + mRender.newTouchPosition(0, 0, 0, pointerId); + } + int count = ev.getHistorySize(); + int pcount = ev.getPointerCount(); + + for (int p=0; p < pcount; p++) { + int id = ev.getPointerId(p); + mRender.newTouchPosition(ev.getX(p), + ev.getY(p), + ev.getPressure(p), + id); + + for (int i=0; i < count; i++) { + mRender.newTouchPosition(ev.getHistoricalX(p, i), + ev.getHistoricalY(p, i), + ev.getHistoricalPressure(p, i), + id); + } + } + return true; + } + */ +} + + diff --git a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs new file mode 100644 index 0000000..494ff35 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs @@ -0,0 +1,173 @@ +#include "shared.rsh" + +const int TEST_COUNT = 1; + +#pragma rs export_var(g_results) +#pragma rs export_func(doTest) + + +static float data_f1[1025]; +static float4 data_f4[1025]; + +static void test_mad4(uint32_t index) { + start(); + + float total = 0; + // Do ~1 billion ops + for (int ct=0; ct < 1000 * (1000 / 80); ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = (data_f4[i] * 0.02f + + data_f4[i+1] * 0.04f + + data_f4[i+2] * 0.05f + + data_f4[i+3] * 0.1f + + data_f4[i+4] * 0.2f + + data_f4[i+5] * 0.2f + + data_f4[i+6] * 0.1f + + data_f4[i+7] * 0.05f + + data_f4[i+8] * 0.04f + + data_f4[i+9] * 0.02f + 1.f); + } + } + + float time = end(index); + rsDebug("fp_mad4 M ops", 1000.f / time); +} + +static void test_mad(uint32_t index) { + start(); + + float total = 0; + // Do ~1 billion ops + for (int ct=0; ct < 1000 * (1000 / 20); ct++) { + for (int i=0; i < (1000); i++) { + data_f1[i] = (data_f1[i] * 0.02f + + data_f1[i+1] * 0.04f + + data_f1[i+2] * 0.05f + + data_f1[i+3] * 0.1f + + data_f1[i+4] * 0.2f + + data_f1[i+5] * 0.2f + + data_f1[i+6] * 0.1f + + data_f1[i+7] * 0.05f + + data_f1[i+8] * 0.04f + + data_f1[i+9] * 0.02f + 1.f); + } + } + + float time = end(index); + rsDebug("fp_mad M ops", 1000.f / time); +} + +static void test_norm(uint32_t index) { + start(); + + float total = 0; + // Do ~10 M ops + for (int ct=0; ct < 1000 * 10; ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = normalize(data_f4[i]); + } + } + + float time = end(index); + rsDebug("fp_norm M ops", 10.f / time); +} + +static void test_sincos4(uint32_t index) { + start(); + + float total = 0; + // Do ~10 M ops + for (int ct=0; ct < 1000 * 10 / 4; ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = sin(data_f4[i]) * cos(data_f4[i]); + } + } + + float time = end(index); + rsDebug("fp_sincos4 M ops", 10.f / time); +} + +static void test_sincos(uint32_t index) { + start(); + + float total = 0; + // Do ~10 M ops + for (int ct=0; ct < 1000 * 10; ct++) { + for (int i=0; i < (1000); i++) { + data_f1[i] = sin(data_f1[i]) * cos(data_f1[i]); + } + } + + float time = end(index); + rsDebug("fp_sincos M ops", 10.f / time); +} + +static void test_clamp(uint32_t index) { + start(); + + // Do ~100 M ops + for (int ct=0; ct < 1000 * 100; ct++) { + for (int i=0; i < (1000); i++) { + data_f1[i] = clamp(data_f1[i], -1.f, 1.f); + } + } + + float time = end(index); + rsDebug("fp_clamp M ops", 100.f / time); + + start(); + // Do ~100 M ops + for (ct=0; ct < 1000 * 100; ct++) { + for (int i=0; i < (1000); i++) { + if (data_f1[i] < -1.f) data_f1[i] = -1.f; + if (data_f1[i] > -1.f) data_f1[i] = 1.f; + } + } + + time = end(index); + rsDebug("fp_clamp ref M ops", 100.f / time); +} + +static void test_clamp4(uint32_t index) { + start(); + + float total = 0; + // Do ~100 M ops + for (int ct=0; ct < 1000 * 100 /4; ct++) { + for (int i=0; i < (1000); i++) { + data_f4[i] = clamp(data_f4[i], -1.f, 1.f); + } + } + + float time = end(index); + rsDebug("fp_clamp4 M ops", 100.f / time); +} + +void doTest(uint32_t index, int test_num) { + for (int x=0; x < 1025; x++) { + data_f1[x] = (x & 0xf) * 0.1f; + data_f4[x].x = (x & 0xf) * 0.1f; + data_f4[x].y = (x & 0xf0) * 0.1f; + data_f4[x].z = (x & 0x33) * 0.1f; + data_f4[x].w = (x & 0x77) * 0.1f; + } + + test_mad4(index); + test_mad(index); + + for (x=0; x < 1025; x++) { + data_f1[x] = (x & 0xf) * 0.1f + 1.f; + data_f4[x].x = (x & 0xf) * 0.1f + 1.f; + data_f4[x].y = (x & 0xf0) * 0.1f + 1.f; + data_f4[x].z = (x & 0x33) * 0.1f + 1.f; + data_f4[x].w = (x & 0x77) * 0.1f + 1.f; + } + + test_norm(index); + test_sincos4(index); + test_sincos(index); + test_clamp4(index); + test_clamp(index); +} + + diff --git a/libs/rs/java/tests/src/com/android/rs/test/shared.rsh b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh new file mode 100644 index 0000000..1773e47 --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh @@ -0,0 +1,25 @@ +#pragma version(1) + +#pragma rs java_package_name(com.android.rs.test) + +typedef struct TestResult_s { + rs_allocation name; + bool pass; + float score; + int64_t time; +} TestResult; +TestResult *g_results; + +static int64_t g_time; + +static void start(void) { + g_time = rsUptimeMillis(); +} + +static float end(uint32_t idx) { + int64_t t = rsUptimeMillis() - g_time; + //g_results[idx].time = t; + //rsDebug("test time", (int)t); + return ((float)t) / 1000.f; +} + diff --git a/libs/rs/java/tests/src/com/android/rs/test/test_root.rs b/libs/rs/java/tests/src/com/android/rs/test/test_root.rs new file mode 100644 index 0000000..72b391d --- /dev/null +++ b/libs/rs/java/tests/src/com/android/rs/test/test_root.rs @@ -0,0 +1,26 @@ +// Fountain test script +#pragma version(1) + +#pragma rs java_package_name(com.android.rs.test) + +#pragma stateFragment(parent) + +#include "rs_graphics.rsh" + + +typedef struct TestResult { + rs_allocation name; + bool pass; + float score; +} TestResult_t; +TestResult_t *results; + +#pragma rs export_var(results) +//#pragma rs export_func(addParticles) + +int root() { + + return 0; +} + + diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h index 455ece7..0a20344 100644 --- a/libs/rs/rsScript.h +++ b/libs/rs/rsScript.h @@ -56,6 +56,8 @@ public: char * mScriptText; uint32_t mScriptTextLength; + + bool mIsThreadable; }; Enviroment_t mEnviroment; diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index 7c7b037..a140e22 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -278,7 +278,7 @@ void ScriptC::runForEach(Context *rsc, } - if ((rsc->getWorkerPoolSize() > 1) && + if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable && ((mtls.dimY * mtls.dimZ * mtls.dimArray) > 1)) { //LOGE("launch 1"); @@ -350,10 +350,12 @@ void ScriptCState::clear() 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; } + s->mEnviroment.mIsThreadable = false; sym = ScriptCState::lookupSymbolCL(name); if (sym) { return sym->mPtr; @@ -371,8 +373,9 @@ void ScriptCState::runCompiler(Context *rsc, ScriptC *s) LOGV("ScriptCState::runCompiler "); s->mBccScript = bccCreateScript(); + s->mEnviroment.mIsThreadable = true; bccScriptBitcode(s->mBccScript, s->mEnviroment.mScriptText, s->mEnviroment.mScriptTextLength); - bccRegisterSymbolCallback(s->mBccScript, symbolLookup, NULL); + bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s); bccCompileScript(s->mBccScript); bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot); bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit); diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh index 45f6bf4..bb4aafb 100644 --- a/libs/rs/scriptc/rs_math.rsh +++ b/libs/rs/scriptc/rs_math.rsh @@ -112,8 +112,19 @@ extern void __attribute__((overloadable)) extern void __attribute__((overloadable)) rsSendToClientBlocking(int cmdID, const void *data, uint len); + // Script to Script +enum rs_for_each_strategy { + RS_FOR_EACH_STRATEGY_SERIAL, + RS_FOR_EACH_STRATEGY_DONT_CARE, + RS_FOR_EACH_STRATEGY_DST_LINEAR, + RS_FOR_EACH_STRATEGY_TILE_SMALL, + RS_FOR_EACH_STRATEGY_TILE_MEDIUM, + RS_FOR_EACH_STRATEGY_TILE_LARGE +}; + typedef struct rs_script_call { + enum rs_for_each_strategy strategy; uint32_t xStart; uint32_t xEnd; uint32_t yStart; @@ -122,7 +133,6 @@ typedef struct rs_script_call { uint32_t zEnd; uint32_t arrayStart; uint32_t arrayEnd; - } rs_script_call_t; extern void __attribute__((overloadable)) diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index efdad43..f2653cf 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -1216,7 +1216,7 @@ status_t AwesomePlayer::finishSetDataSource_l() { MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); return setDataSource_l(extractor); - } else if (!strcmp("rtsp://gtalk", mUri.string())) { + } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) { if (mLooper == NULL) { mLooper = new ALooper; mLooper->start( @@ -1225,6 +1225,22 @@ status_t AwesomePlayer::finishSetDataSource_l() { PRIORITY_HIGHEST); } + const char *startOfCodecString = &mUri.string()[13]; + const char *startOfSlash1 = strchr(startOfCodecString, '/'); + if (startOfSlash1 == NULL) { + return BAD_VALUE; + } + const char *startOfWidthString = &startOfSlash1[1]; + const char *startOfSlash2 = strchr(startOfWidthString, '/'); + if (startOfSlash2 == NULL) { + return BAD_VALUE; + } + const char *startOfHeightString = &startOfSlash2[1]; + + String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString); + String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString); + String8 heightString(startOfHeightString); + #if 0 mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434); mLooper->registerHandler(mRTPPusher); @@ -1251,8 +1267,8 @@ status_t AwesomePlayer::finishSetDataSource_l() { "a=rtpmap:97 AMR/8000/1\r\n" "a=fmtp:97 octet-align\r\n"; #elif 1 - // My GTalk H.264 SDP - static const char *raw = + String8 sdp; + sdp.appendFormat( "v=0\r\n" "o=- 64 233572944 IN IP4 127.0.0.0\r\n" "s=QuickTime\r\n" @@ -1262,24 +1278,16 @@ status_t AwesomePlayer::finishSetDataSource_l() { "m=video 5434 RTP/AVP 97\r\n" "c=IN IP4 127.0.0.1\r\n" "b=AS:30\r\n" - "a=rtpmap:97 H264/90000\r\n" - "a=cliprect:0,0,200,320\r\n" - "a=framesize:97 320-200\r\n"; -#else - // GTalk H263 SDP - static const char *raw = - "v=0\r\n" - "o=- 64 233572944 IN IP4 127.0.0.0\r\n" - "s=QuickTime\r\n" - "t=0 0\r\n" - "a=range:npt=0-315\r\n" - "a=isma-compliance:2,2.0,2\r\n" - "m=video 5434 RTP/AVP 98\r\n" - "c=IN IP4 127.0.0.1\r\n" - "b=AS:30\r\n" - "a=rtpmap:98 H263-1998/90000\r\n" - "a=cliprect:0,0,200,320\r\n" - "a=framesize:98 320-200\r\n"; + "a=rtpmap:97 %s/90000\r\n" + "a=cliprect:0,0,%s,%s\r\n" + "a=framesize:97 %s-%s\r\n", + + codecString.string(), + heightString.string(), widthString.string(), + widthString.string(), heightString.string() + ); + const char *raw = sdp.string(); + #endif sp<ASessionDescription> desc = new ASessionDescription; diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp index 0d89e02..389180c 100644 --- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp +++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp @@ -98,6 +98,7 @@ AVCEncoder::AVCEncoder( : mSource(source), mMeta(meta), mNumInputFrames(-1), + mPrevTimestampUs(-1), mStarted(false), mInputBuffer(NULL), mInputFrameData(NULL), @@ -391,8 +392,6 @@ status_t AVCEncoder::read( if (err != OK) { LOGE("Failed to read input video frame: %d", err); outputBuffer->release(); - mInputBuffer->release(); - mInputBuffer = NULL; return err; } diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp index 5ea5859..a011137 100644 --- a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp +++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp @@ -69,6 +69,7 @@ M4vH263Encoder::M4vH263Encoder( mMeta(meta), mNumInputFrames(-1), mNextModTimeUs(0), + mPrevTimestampUs(-1), mStarted(false), mInputBuffer(NULL), mInputFrameData(NULL), @@ -292,8 +293,6 @@ status_t M4vH263Encoder::read( if (OK != mSource->read(&mInputBuffer, options)) { LOGE("Failed to read from data source"); outputBuffer->release(); - mInputBuffer->release(); - mInputBuffer = NULL; return UNKNOWN_ERROR; } diff --git a/packages/DefaultContainerService/res/values-cs/strings.xml b/packages/DefaultContainerService/res/values-cs/strings.xml index 0179e85..216d715 100644 --- a/packages/DefaultContainerService/res/values-cs/strings.xml +++ b/packages/DefaultContainerService/res/values-cs/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Media Container Service"</string> + <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-da/strings.xml b/packages/DefaultContainerService/res/values-da/strings.xml index 0179e85..5243028 100644 --- a/packages/DefaultContainerService/res/values-da/strings.xml +++ b/packages/DefaultContainerService/res/values-da/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Media Container Service"</string> + <string name="service_name" msgid="4841491635055379553">"Hjælp til pakkeadgang"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-de/strings.xml b/packages/DefaultContainerService/res/values-de/strings.xml index 5d12956..216d715 100644 --- a/packages/DefaultContainerService/res/values-de/strings.xml +++ b/packages/DefaultContainerService/res/values-de/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Medien-Containerdienst"</string> + <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-el/strings.xml b/packages/DefaultContainerService/res/values-el/strings.xml index b0b5794..a4d8144 100644 --- a/packages/DefaultContainerService/res/values-el/strings.xml +++ b/packages/DefaultContainerService/res/values-el/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Υπηρεσία Media Container"</string> + <string name="service_name" msgid="4841491635055379553">"Βοηθός πρόσβασης πακέτου"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-es-rUS/strings.xml b/packages/DefaultContainerService/res/values-es-rUS/strings.xml index cf893de..670c2c5 100644 --- a/packages/DefaultContainerService/res/values-es-rUS/strings.xml +++ b/packages/DefaultContainerService/res/values-es-rUS/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Servicio de contención de medios"</string> + <string name="service_name" msgid="4841491635055379553">"Asist. p/acceder al paq."</string> </resources> diff --git a/packages/DefaultContainerService/res/values-es/strings.xml b/packages/DefaultContainerService/res/values-es/strings.xml index 6817520..022c461 100644 --- a/packages/DefaultContainerService/res/values-es/strings.xml +++ b/packages/DefaultContainerService/res/values-es/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Servicio de contenedor de medios"</string> + <string name="service_name" msgid="4841491635055379553">"Ayudante acceso a paquete"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-fr/strings.xml b/packages/DefaultContainerService/res/values-fr/strings.xml index 3b4a90d..5c458bc 100644 --- a/packages/DefaultContainerService/res/values-fr/strings.xml +++ b/packages/DefaultContainerService/res/values-fr/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Service de support multimédia"</string> + <string name="service_name" msgid="4841491635055379553">"Aide accès au package"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-it/strings.xml b/packages/DefaultContainerService/res/values-it/strings.xml index 55bd6e5..216d715 100644 --- a/packages/DefaultContainerService/res/values-it/strings.xml +++ b/packages/DefaultContainerService/res/values-it/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Servizio Media Container"</string> + <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-ja/strings.xml b/packages/DefaultContainerService/res/values-ja/strings.xml index dc1dfea..2f57e4e 100644 --- a/packages/DefaultContainerService/res/values-ja/strings.xml +++ b/packages/DefaultContainerService/res/values-ja/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"メディアコンテナサービス"</string> + <string name="service_name" msgid="4841491635055379553">"パッケージアクセス支援ツール"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-ko/strings.xml b/packages/DefaultContainerService/res/values-ko/strings.xml index 0179e85..0304972 100644 --- a/packages/DefaultContainerService/res/values-ko/strings.xml +++ b/packages/DefaultContainerService/res/values-ko/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Media Container Service"</string> + <string name="service_name" msgid="4841491635055379553">"패키지 액세스 도움말"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-nb/strings.xml b/packages/DefaultContainerService/res/values-nb/strings.xml index 0179e85..637f54d 100644 --- a/packages/DefaultContainerService/res/values-nb/strings.xml +++ b/packages/DefaultContainerService/res/values-nb/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Media Container Service"</string> + <string name="service_name" msgid="4841491635055379553">"Hjelpeprogram for pakketilgang"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-nl/strings.xml b/packages/DefaultContainerService/res/values-nl/strings.xml index 0179e85..9ece040 100644 --- a/packages/DefaultContainerService/res/values-nl/strings.xml +++ b/packages/DefaultContainerService/res/values-nl/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Media Container Service"</string> + <string name="service_name" msgid="4841491635055379553">"Helper voor pakkettoegang"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-pl/strings.xml b/packages/DefaultContainerService/res/values-pl/strings.xml index 0c96f3d..216d715 100644 --- a/packages/DefaultContainerService/res/values-pl/strings.xml +++ b/packages/DefaultContainerService/res/values-pl/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Usługa kontenera multimediów"</string> + <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-pt-rPT/strings.xml b/packages/DefaultContainerService/res/values-pt-rPT/strings.xml index 0179e85..5c03669 100644 --- a/packages/DefaultContainerService/res/values-pt-rPT/strings.xml +++ b/packages/DefaultContainerService/res/values-pt-rPT/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Media Container Service"</string> + <string name="service_name" msgid="4841491635055379553">"Ajuda p/ aceder pacotes"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-pt/strings.xml b/packages/DefaultContainerService/res/values-pt/strings.xml index 00b90de..5fbd949 100644 --- a/packages/DefaultContainerService/res/values-pt/strings.xml +++ b/packages/DefaultContainerService/res/values-pt/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Serviço de recipiente de mídia"</string> + <string name="service_name" msgid="4841491635055379553">"Assistente de pacote"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-ru/strings.xml b/packages/DefaultContainerService/res/values-ru/strings.xml index 0179e85..ccb0c53 100644 --- a/packages/DefaultContainerService/res/values-ru/strings.xml +++ b/packages/DefaultContainerService/res/values-ru/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Media Container Service"</string> + <string name="service_name" msgid="4841491635055379553">"Мастер доступа к пакетам"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-sv/strings.xml b/packages/DefaultContainerService/res/values-sv/strings.xml index b097814..097a709 100644 --- a/packages/DefaultContainerService/res/values-sv/strings.xml +++ b/packages/DefaultContainerService/res/values-sv/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Medietjänst"</string> + <string name="service_name" msgid="4841491635055379553">"Hjälp med paketåtkomst"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-tr/strings.xml b/packages/DefaultContainerService/res/values-tr/strings.xml index afd870f..12ea674 100644 --- a/packages/DefaultContainerService/res/values-tr/strings.xml +++ b/packages/DefaultContainerService/res/values-tr/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"Ortam Kapsayıcı Hizmeti"</string> + <string name="service_name" msgid="4841491635055379553">"Paket Erişim Yardımcısı"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml b/packages/DefaultContainerService/res/values-zh-rCN/strings.xml index 4f99d1b..982015c 100644 --- a/packages/DefaultContainerService/res/values-zh-rCN/strings.xml +++ b/packages/DefaultContainerService/res/values-zh-rCN/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"媒体容器服务"</string> + <string name="service_name" msgid="4841491635055379553">"包裹访问帮助程序"</string> </resources> diff --git a/packages/DefaultContainerService/res/values-zh-rTW/strings.xml b/packages/DefaultContainerService/res/values-zh-rTW/strings.xml index 38870f6..9a43509 100644 --- a/packages/DefaultContainerService/res/values-zh-rTW/strings.xml +++ b/packages/DefaultContainerService/res/values-zh-rTW/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="2260781993795858516">"媒體庫服務"</string> + <string name="service_name" msgid="4841491635055379553">"套件存取輔助程式"</string> </resources> diff --git a/packages/SystemUI/res/drawable-hdpi/battery_0.png b/packages/SystemUI/res/drawable-hdpi/battery_0.png Binary files differnew file mode 100644 index 0000000..f4103a8 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/battery_0.png diff --git a/packages/SystemUI/res/drawable-hdpi/battery_100.png b/packages/SystemUI/res/drawable-hdpi/battery_100.png Binary files differnew file mode 100644 index 0000000..061cbe5 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/battery_100.png diff --git a/packages/SystemUI/res/drawable-hdpi/battery_20.png b/packages/SystemUI/res/drawable-hdpi/battery_20.png Binary files differnew file mode 100644 index 0000000..0064027 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/battery_20.png diff --git a/packages/SystemUI/res/drawable-hdpi/battery_40.png b/packages/SystemUI/res/drawable-hdpi/battery_40.png Binary files differnew file mode 100644 index 0000000..10de0e7 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/battery_40.png diff --git a/packages/SystemUI/res/drawable-hdpi/battery_60.png b/packages/SystemUI/res/drawable-hdpi/battery_60.png Binary files differnew file mode 100644 index 0000000..aa2b8ef --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/battery_60.png diff --git a/packages/SystemUI/res/drawable-hdpi/battery_80.png b/packages/SystemUI/res/drawable-hdpi/battery_80.png Binary files differnew file mode 100644 index 0000000..fe231f0 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/battery_80.png diff --git a/packages/SystemUI/res/drawable-hdpi/signal_0.png b/packages/SystemUI/res/drawable-hdpi/signal_0.png Binary files differnew file mode 100644 index 0000000..00e36c4 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/signal_0.png diff --git a/packages/SystemUI/res/drawable-hdpi/signal_100.png b/packages/SystemUI/res/drawable-hdpi/signal_100.png Binary files differnew file mode 100644 index 0000000..96e52ff --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/signal_100.png diff --git a/packages/SystemUI/res/drawable-hdpi/signal_20.png b/packages/SystemUI/res/drawable-hdpi/signal_20.png Binary files differnew file mode 100644 index 0000000..c0f652a --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/signal_20.png diff --git a/packages/SystemUI/res/drawable-hdpi/signal_40.png b/packages/SystemUI/res/drawable-hdpi/signal_40.png Binary files differnew file mode 100644 index 0000000..995dd8e --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/signal_40.png diff --git a/packages/SystemUI/res/drawable-hdpi/signal_60.png b/packages/SystemUI/res/drawable-hdpi/signal_60.png Binary files differnew file mode 100644 index 0000000..51e31ba --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/signal_60.png diff --git a/packages/SystemUI/res/drawable-hdpi/signal_80.png b/packages/SystemUI/res/drawable-hdpi/signal_80.png Binary files differnew file mode 100644 index 0000000..afa656e --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/signal_80.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_0.png b/packages/SystemUI/res/drawable-mdpi/battery_0.png Binary files differnew file mode 100644 index 0000000..b5d36cc --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_100.png b/packages/SystemUI/res/drawable-mdpi/battery_100.png Binary files differnew file mode 100644 index 0000000..75cc409 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_100.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_20.png b/packages/SystemUI/res/drawable-mdpi/battery_20.png Binary files differnew file mode 100644 index 0000000..c0d0030 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_20.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_40.png b/packages/SystemUI/res/drawable-mdpi/battery_40.png Binary files differnew file mode 100644 index 0000000..e301c08 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_40.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_60.png b/packages/SystemUI/res/drawable-mdpi/battery_60.png Binary files differnew file mode 100644 index 0000000..0fde1fa --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_60.png diff --git a/packages/SystemUI/res/drawable-mdpi/battery_80.png b/packages/SystemUI/res/drawable-mdpi/battery_80.png Binary files differnew file mode 100644 index 0000000..15c4e1c --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/battery_80.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_0.png b/packages/SystemUI/res/drawable-mdpi/signal_0.png Binary files differnew file mode 100644 index 0000000..6533677 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_100.png b/packages/SystemUI/res/drawable-mdpi/signal_100.png Binary files differnew file mode 100644 index 0000000..e8976a2 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_100.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_20.png b/packages/SystemUI/res/drawable-mdpi/signal_20.png Binary files differnew file mode 100644 index 0000000..651e2a9 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_20.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_40.png b/packages/SystemUI/res/drawable-mdpi/signal_40.png Binary files differnew file mode 100644 index 0000000..6ba7906 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_40.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_60.png b/packages/SystemUI/res/drawable-mdpi/signal_60.png Binary files differnew file mode 100644 index 0000000..6d2e812 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_60.png diff --git a/packages/SystemUI/res/drawable-mdpi/signal_80.png b/packages/SystemUI/res/drawable-mdpi/signal_80.png Binary files differnew file mode 100644 index 0000000..a152623 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/signal_80.png diff --git a/packages/SystemUI/res/drawable/battery.xml b/packages/SystemUI/res/drawable/battery.xml new file mode 100644 index 0000000..c2294d1 --- /dev/null +++ b/packages/SystemUI/res/drawable/battery.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/drawable/stat_sys_battery.xml +** +** Copyright 2007, 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. +*/ +--> + +<level-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:maxLevel="1" android:drawable="@drawable/battery_0" /> + <item android:maxLevel="5"> + <animation-list android:oneshot="false"> + <item android:drawable="@drawable/battery_0" android:duration="250" /> + <item android:drawable="@drawable/battery_20" android:duration="250" /> + </animation-list> + </item> + <item android:maxLevel="20" android:drawable="@drawable/battery_20" /> + <item android:maxLevel="40" android:drawable="@drawable/battery_40" /> + <item android:maxLevel="60" android:drawable="@drawable/battery_60" /> + <item android:maxLevel="80" android:drawable="@drawable/battery_80" /> + <item android:maxLevel="101" android:drawable="@drawable/battery_100" /> +</level-list> + diff --git a/packages/SystemUI/res/drawable/battery_charging.xml b/packages/SystemUI/res/drawable/battery_charging.xml new file mode 100644 index 0000000..2fd0c6d --- /dev/null +++ b/packages/SystemUI/res/drawable/battery_charging.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/drawable/stat_sys_battery.xml +** +** Copyright 2007, 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. +*/ +--> + +<level-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:maxLevel="20"> + <animation-list android:oneshot="false"> + <item android:drawable="@drawable/battery_0" android:duration="1000" /> + <item android:drawable="@drawable/battery_20" android:duration="1000" /> + </animation-list> + </item> + <item android:maxLevel="40"> + <animation-list android:oneshot="false"> + <item android:drawable="@drawable/battery_20" android:duration="1000" /> + <item android:drawable="@drawable/battery_40" android:duration="1000" /> + </animation-list> + </item> + <item android:maxLevel="60"> + <animation-list android:oneshot="false"> + <item android:drawable="@drawable/battery_40" android:duration="1000" /> + <item android:drawable="@drawable/battery_60" android:duration="1000" /> + </animation-list> + </item> + <item android:maxLevel="80"> + <animation-list android:oneshot="false"> + <item android:drawable="@drawable/battery_60" android:duration="1000" /> + <item android:drawable="@drawable/battery_80" android:duration="1000" /> + </animation-list> + </item> + <item android:maxLevel="92"> + <animation-list android:oneshot="false"> + <item android:drawable="@drawable/battery_80" android:duration="1000" /> + <item android:drawable="@drawable/battery_100" android:duration="1000" /> + </animation-list> + </item> + <item android:maxLevel="101" android:drawable="@drawable/battery_100" /> +</level-list> + diff --git a/packages/SystemUI/res/drawable/signal.xml b/packages/SystemUI/res/drawable/signal.xml new file mode 100644 index 0000000..8b4f56b --- /dev/null +++ b/packages/SystemUI/res/drawable/signal.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/drawable/stat_sys_battery.xml +** +** Copyright 2007, 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. +*/ +--> + +<level-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:maxLevel="01" android:drawable="@drawable/signal_0" /> + <item android:maxLevel="20" android:drawable="@drawable/signal_20" /> + <item android:maxLevel="40" android:drawable="@drawable/signal_40" /> + <item android:maxLevel="60" android:drawable="@drawable/signal_60" /> + <item android:maxLevel="80" android:drawable="@drawable/signal_80" /> + <item android:maxLevel="101" android:drawable="@drawable/signal_100" /> + +</level-list> + diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_center.xml b/packages/SystemUI/res/layout-xlarge/status_bar_center.xml index c32e997..775fea0 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_center.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_center.xml @@ -36,18 +36,20 @@ android:padding="2dip" /> <ImageView - android:layout_width="wrap_content" + android:id="@+id/battery" + android:layout_width="50dip" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@id/clock" - android:src="@drawable/dots_empty" + android:src="@drawable/battery" /> <ImageView - android:layout_width="wrap_content" + android:id="@+id/signal" + android:layout_width="50dip" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@id/clock" - android:src="@drawable/dots_full" + android:src="@drawable/signal" /> </RelativeLayout> diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml index fc37900..e5b2f53 100644 --- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml +++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_system.xml @@ -96,6 +96,7 @@ <TextView android:id="@+id/battery_info" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="center" android:layout_below="@id/battery_meter" /> @@ -121,12 +122,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" - android:src="@drawable/dots_full" + android:src="@drawable/signal" /> <TextView android:id="@+id/signal_info" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="center" android:layout_below="@id/signal_meter" /> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java index 236b521..c864daa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SystemPanel.java @@ -78,14 +78,25 @@ public class SystemPanel extends LinearLayout { private ImageButton mOrientationButton; private ImageButton mAirplaneButton; + private ImageView mBatteryMeter; + private ImageView mSignalMeter; + + private TextView mBatteryText; + private TextView mSignalText; + private final AudioManager mAudioManager; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { + final String action = intent.getAction(); + if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { mSoundButton.setAlpha(getSilentMode() ? 0x7F : 0xFF); + } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { + // hack for now + mBar.updateBatteryDisplay(intent.getIntExtra("level", 0), + (intent.getIntExtra("plugged", 0) != 0)); } } }; @@ -93,6 +104,12 @@ public class SystemPanel extends LinearLayout { public void setBar(TabletStatusBarService bar) { mBar = bar; } + + public void setBatteryLevel(int level, boolean plugged) { + mBatteryMeter.setImageResource(plugged ? R.drawable.battery_charging : R.drawable.battery); + mBatteryMeter.setImageLevel(level); + mBatteryText.setText(String.format("Battery: %d%%", level)); + } public SystemPanel(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -151,8 +168,21 @@ public class SystemPanel extends LinearLayout { } }); - IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); + IntentFilter filter = new IntentFilter(); + filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(Intent.ACTION_POWER_CONNECTED); getContext().registerReceiver(mReceiver, filter); + + mBatteryMeter = (ImageView)findViewById(R.id.battery_meter); + mBatteryMeter.setImageResource(R.drawable.battery); + mBatteryMeter.setImageLevel(0); + mSignalMeter = (ImageView)findViewById(R.id.signal_meter); + mBatteryMeter.setImageResource(R.drawable.signal); + mBatteryMeter.setImageLevel(0); + + mBatteryText = (TextView)findViewById(R.id.battery_info); + mSignalText = (TextView)findViewById(R.id.signal_info); } public void onDetachedFromWindow() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java index 9c86f2d..b0ffaa5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java @@ -75,6 +75,9 @@ public class TabletStatusBarService extends StatusBarService { ViewGroup mPile; TextView mClearButton; + ImageView mBatteryMeter; + ImageView mSignalMeter; + NotificationIconArea.IconLayout mIconLayout; KickerController mKicker; @@ -151,6 +154,10 @@ public class TabletStatusBarService extends StatusBarService { mKicker = new KickerController((Context)this, mStatusBarView); + // System info (center) + mBatteryMeter = (ImageView) sb.findViewById(R.id.battery); + mSignalMeter = (ImageView) sb.findViewById(R.id.signal); + // Add the windows addPanelWindows(); @@ -198,18 +205,27 @@ public class TabletStatusBarService extends StatusBarService { } } } + + StatusBarIcon mBatterySBI; + StatusBarIcon mSignalSBI; + public void updateBatteryDisplay(int level, boolean plugged) { + if (DEBUG) Slog.d(TAG, "battery=" + level + (plugged ? " - plugged" : " - unplugged")); + mBatteryMeter.setImageResource(plugged ? R.drawable.battery_charging : R.drawable.battery); + mBatteryMeter.setImageLevel(level); + mSystemPanel.setBatteryLevel(level, plugged); + } public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { - // TODO + if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon); } public void updateIcon(String slot, int index, int viewIndex, StatusBarIcon old, StatusBarIcon icon) { - // TODO + if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon); } public void removeIcon(String slot, int index, int viewIndex) { - // TODO + if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")"); } public void addNotification(IBinder key, StatusBarNotification notification) { diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 546c0f4..a410fa4 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -647,10 +647,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mActionBar.isOverflowReserved()) { if (!mActionBar.isOverflowMenuShowing()) { final Callback cb = getCallback(); - if (cb != null) { - if (cb.onPreparePanel(featureId, st.createdPanelView, st.menu)) { - playSoundEffect = mActionBar.showOverflowMenu(); - } + if (cb != null && + cb.onPreparePanel(featureId, st.createdPanelView, st.menu)) { + playSoundEffect = mActionBar.showOverflowMenu(); } } else { playSoundEffect = mActionBar.hideOverflowMenu(); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 8ca880b..0291d78 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -34,7 +34,7 @@ namespace android { // --------------------------------------------------------------------------- HWComposer::HWComposer() - : mModule(0), mHwc(0), mList(0), + : mModule(0), mHwc(0), mList(0), mCapacity(0), mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE) { int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); @@ -63,10 +63,13 @@ void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) { } status_t HWComposer::createWorkList(size_t numLayers) { - if (mHwc && (!mList || mList->numHwLayers < numLayers)) { - free(mList); - size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t); - mList = (hwc_layer_list_t*)malloc(size); + if (mHwc) { + if (!mList || mCapacity < numLayers) { + free(mList); + size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t); + mList = (hwc_layer_list_t*)malloc(size); + mCapacity = numLayers; + } mList->flags = HWC_GEOMETRY_CHANGED; mList->numHwLayers = numLayers; } @@ -84,12 +87,12 @@ status_t HWComposer::commit() const { return (status_t)err; } -HWComposer::iterator HWComposer::begin() { - return mList ? &(mList->hwLayers[0]) : NULL; +size_t HWComposer::getNumLayers() const { + return mList ? mList->numHwLayers : 0; } -HWComposer::iterator HWComposer::end() { - return mList ? &(mList->hwLayers[mList->numHwLayers]) : NULL; +hwc_layer_t* HWComposer::getLayers() const { + return mList ? mList->hwLayers : 0; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 729f23b..c5d5c2b 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -49,16 +49,14 @@ public: status_t commit() const; - typedef hwc_layer_t const * const_iterator; - typedef hwc_layer_t* iterator; - - iterator begin(); - iterator end(); + size_t getNumLayers() const; + hwc_layer_t* getLayers() const; private: hw_module_t const* mModule; hwc_composer_device_t* mHwc; hwc_layer_list_t* mList; + size_t mCapacity; hwc_display_t mDpy; hwc_surface_t mSur; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 47bb4c1..d257897 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -755,10 +755,9 @@ void SurfaceFlinger::handleWorkList() const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ); const size_t count = currentLayers.size(); hwc.createWorkList(count); - HWComposer::iterator cur(hwc.begin()); - HWComposer::iterator last(hwc.end()); - for (size_t i=0 ; (i<count) && (cur!=last) ; ++i, ++cur) { - currentLayers[i]->setGeometry(cur); + hwc_layer_t* const cur(hwc.getLayers()); + for (size_t i=0 ; cur && i<count ; i++) { + currentLayers[i]->setGeometry(&cur[i]); } } } @@ -829,47 +828,43 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) status_t err = NO_ERROR; const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); - const size_t count = layers.size(); + size_t count = layers.size(); const DisplayHardware& hw(graphicPlane(0).displayHardware()); HWComposer& hwc(hw.getHwComposer()); - HWComposer::iterator cur(hwc.begin()); - HWComposer::iterator last(hwc.end()); + hwc_layer_t* const cur(hwc.getLayers()); - // update the per-frame h/w composer data for each layer - if (cur != last) { - for (size_t i=0 ; i<count && cur!=last ; ++i, ++cur) { - layers[i]->setPerFrameData(cur); - } - err = hwc.prepare(); - LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); - } + LOGE_IF(cur && hwc.getNumLayers() != count, + "HAL number of layers (%d) doesn't match surfaceflinger (%d)", + hwc.getNumLayers(), count); - // and then, render the layers targeted at the framebuffer - Region transparent(hw.bounds()); - for (size_t i=0 ; i<count ; ++i) { + // just to be extra-safe, use the smallest count + if (hwc.initCheck() == NO_ERROR) { + count = count < hwc.getNumLayers() ? count : hwc.getNumLayers(); + } - // see if we need to skip this layer - if (!err && cur != last) { - if (!((cur->compositionType == HWC_FRAMEBUFFER) || - (cur->flags & HWC_SKIP_LAYER))) { - ++cur; - continue; + /* + * update the per-frame h/w composer data for each layer + * and build the transparent region of the FB + */ + Region transparent; + if (cur) { + for (size_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(layers[i]); + layer->setPerFrameData(&cur[i]); + if (cur[i].hints & HWC_HINT_CLEAR_FB) { + if (!(layer->needsBlending())) { + transparent.orSelf(layer->visibleRegionScreen); + } } - ++cur; - } - - // draw the layer into the framebuffer - const sp<LayerBase>& layer(layers[i]); - transparent.subtractSelf(layer->visibleRegionScreen); - const Region clip(dirty.intersect(layer->visibleRegionScreen)); - if (!clip.isEmpty()) { - layer->draw(clip); } + err = hwc.prepare(); + LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); } - // finally clear everything we didn't draw as a result of calling - // prepare (this leaves the FB transparent). + /* + * clear the area of the FB that need to be transparent + */ transparent.andSelf(dirty); if (!transparent.isEmpty()) { glClearColor(0,0,0,0); @@ -883,6 +878,25 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) glClear(GL_COLOR_BUFFER_BIT); } } + + + /* + * and then, render the layers targeted at the framebuffer + */ + for (size_t i=0 ; i<count ; i++) { + if (cur) { + if (!(cur[i].compositionType == HWC_FRAMEBUFFER) || + cur[i].flags & HWC_SKIP_LAYER) { + // skip layers handled by the HAL + continue; + } + } + const sp<LayerBase>& layer(layers[i]); + const Region clip(dirty.intersect(layer->visibleRegionScreen)); + if (!clip.isEmpty()) { + layer->draw(clip); + } + } } void SurfaceFlinger::unlockClients() diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 11315ce..b0fa0f5 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1385,7 +1385,7 @@ public class PhoneNumberUtils * Normalize a phone number by removing the characters other than digits. If * the given number has keypad letters, the letters will be converted to * digits first. - * + * * @param phoneNumber * the number to be normalized. * @return the normalized number. @@ -1397,9 +1397,9 @@ public class PhoneNumberUtils int len = phoneNumber.length(); for (int i = 0; i < len; i++) { char c = phoneNumber.charAt(i); - if (PhoneNumberUtils.isISODigit(c)) { + if ((i == 0 && c == '+') || PhoneNumberUtils.isISODigit(c)) { sb.append(c); - } else if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') { + } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { return normalizeNumber(PhoneNumberUtils.convertKeypadLettersToDigits(phoneNumber)); } } @@ -1779,6 +1779,15 @@ public class PhoneNumberUtils } /** + * @hide + * @param number + * @return true if number contains @ + */ + public static boolean isUriNumber(String number) { + return number != null && number.contains("@"); + } + + /** * This function handles the plus code conversion within NANP CDMA network * If the number format is * 1)+1NANP,remove +, diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java index 2934e6a..819cfbe 100644 --- a/telephony/java/com/android/internal/telephony/CallManager.java +++ b/telephony/java/com/android/internal/telephony/CallManager.java @@ -21,12 +21,18 @@ import android.os.AsyncResult; import android.os.Handler; import android.os.Message; import android.os.RegistrantList; +import android.util.Log; + import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; + import java.util.ArrayList; import java.util.Collections; import java.util.List; + + /** * @hide * @@ -46,6 +52,9 @@ import java.util.List; */ public final class CallManager { + private static final String LOG_TAG ="GSM"; + private static final boolean LOCAL_DEBUG = true; + private static final int EVENT_DISCONNECT = 100; private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101; private static final int EVENT_NEW_RINGING_CONNECTION = 102; @@ -180,7 +189,7 @@ public final class CallManager { public Phone.State getState() { Phone.State s = Phone.State.IDLE; - for(Phone phone : mPhones) { + for (Phone phone : mPhones) { if (phone.getState() == Phone.State.RINGING) { return Phone.State.RINGING; } else if (phone.getState() == Phone.State.OFFHOOK) { @@ -191,6 +200,41 @@ public final class CallManager { } /** + * @return the service state of CallManager, which represents the + * highest priority state of all the service states of phones + * + * The priority is defined as + * + * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF + * + */ + + public int getServiceState() { + int resultState = ServiceState.STATE_OUT_OF_SERVICE; + + for (Phone phone : mPhones) { + int serviceState = phone.getServiceState().getState(); + if (serviceState == ServiceState.STATE_IN_SERVICE) { + // IN_SERVICE has the highest priority + resultState = serviceState; + break; + } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) { + // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF + // Note: EMERGENCY_ONLY is not in use at this moment + if ( resultState == ServiceState.STATE_EMERGENCY_ONLY || + resultState == ServiceState.STATE_POWER_OFF) { + resultState = serviceState; + } + } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) { + if (resultState == ServiceState.STATE_POWER_OFF) { + resultState = serviceState; + } + } + } + return resultState; + } + + /** * Register phone to CallManager * @param phone * @return true if register successfully @@ -211,6 +255,34 @@ public final class CallManager { } /** + * return the default phone or null if no phone available + */ + public Phone getDefaultPhone() { + return mDefaultPhone; + } + + /** + * @return the phone associated with the foreground call + */ + public Phone getFgPhone() { + return getActiveFgCall().getPhone(); + } + + /** + * @return the phone associated with the background call + */ + public Phone getBgPhone() { + return getFirstActiveBgCall().getPhone(); + } + + /** + * @return the phone associated with the ringing call + */ + public Phone getRingingPhone() { + return getFirstActiveRingingCall().getPhone(); + } + + /** * unregister phone from CallManager * @param phone */ @@ -291,9 +363,13 @@ public final class CallManager { if ( hasActiveFgCall() ) { Phone activePhone = getActiveFgCall().getPhone(); - boolean hasBgCall = activePhone.getBackgroundCall().isIdle(); + boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle()); boolean sameChannel = (activePhone == ringingPhone); + if (LOCAL_DEBUG) { + Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel); + } + if (sameChannel && hasBgCall) { getActiveFgCall().hangup(); } else if (!sameChannel && !hasBgCall) { @@ -322,8 +398,15 @@ public final class CallManager { } /** - * Places any active calls on hold, and makes any held calls - * active. Switch occurs asynchronously and may fail. + * Places active call on hold, and makes held call active. + * Switch occurs asynchronously and may fail. + * + * There are 4 scenarios + * 1. only active call but no held call, aka, hold + * 2. no active call but only held call, aka, unhold + * 3. both active and held calls from same phone, aka, swap + * 4. active and held calls from different phones, aka, phone swap + * * Final notification occurs via * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, * java.lang.Object) registerForPreciseCallStateChanged()}. @@ -344,11 +427,13 @@ public final class CallManager { heldPhone = heldCall.getPhone(); } - if (activePhone != heldPhone) { + if (activePhone != null) { activePhone.switchHoldingAndActive(); } - heldPhone.switchHoldingAndActive(); + if (heldPhone != null && heldPhone != activePhone) { + heldPhone.switchHoldingAndActive(); + } } /** @@ -398,6 +483,24 @@ public final class CallManager { * handled asynchronously. */ public Connection dial(Phone phone, String dialString) throws CallStateException { + if ( hasActiveFgCall() ) { + Phone activePhone = getActiveFgCall().getPhone(); + boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle()); + + if (LOCAL_DEBUG) { + Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + (activePhone != phone)); + } + + if (activePhone != phone) { + if (hasBgCall) { + Log.d(LOG_TAG, "Hangup"); + getActiveFgCall().hangup(); + } else { + Log.d(LOG_TAG, "Switch"); + activePhone.switchHoldingAndActive(); + } + } + } return phone.dial(dialString); } @@ -975,7 +1078,7 @@ public final class CallManager { * @return list of ringing calls */ public ArrayList<Call> getRingingCalls() { - return mBackgroundCalls; + return mRingingCalls; } /** diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index 769b2fc..784e87d 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -179,6 +179,7 @@ public interface Phone { static final int PHONE_TYPE_NONE = RILConstants.NO_PHONE; static final int PHONE_TYPE_GSM = RILConstants.GSM_PHONE; static final int PHONE_TYPE_CDMA = RILConstants.CDMA_PHONE; + static final int PHONE_TYPE_SIP = RILConstants.SIP_PHONE; // Used for preferred network type // Note NT_* substitute RILConstants.NETWORK_MODE_* above the Phone diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 71a80e0..888f721 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -79,6 +79,7 @@ public interface RILConstants { int NO_PHONE = 0; int GSM_PHONE = 1; int CDMA_PHONE = 2; + int SIP_PHONE = 3; int CDM_TTY_MODE_DISABLED = 0; int CDM_TTY_MODE_ENABLED = 1; diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java index 5ef1c69..88aa78e 100644 --- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java +++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java @@ -524,6 +524,7 @@ public class PhoneNumberUtilsTest extends AndroidTestCase { assertEquals("6502910000", PhoneNumberUtils.normalizeNumber("650 2910000")); assertEquals("1234567", PhoneNumberUtils.normalizeNumber("12,3#4*567")); assertEquals("8004664114", PhoneNumberUtils.normalizeNumber("800-GOOG-114")); + assertEquals("+16502910000", PhoneNumberUtils.normalizeNumber("+1 650 2910000")); } } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java index 9f580a3..784a6d5 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java @@ -89,6 +89,8 @@ public class FileFilter { // This first block of tests are for features for which Android // should pass all tests. They are skipped only temporarily. // TODO: Fix these failing tests and remove them from this list. + ignoreResultList.add("fast/dom/Geolocation/delayed-permission-allowed.html"); // requires layoutTestController.permissionSet + ignoreResultList.add("fast/dom/Geolocation/delayed-permission-denied.html"); // requires layoutTestController.permissionSet ignoreResultList.add("fast/events/touch/basic-multi-touch-events.html"); // Requires multi-touch ignoreResultList.add("fast/events/touch/touch-target.html"); // Requires multi-touch ignoreResultList.add("http/tests/appcache/empty-manifest.html"); // flaky diff --git a/tests/DumpRenderTree2/Android.mk b/tests/DumpRenderTree2/Android.mk index eddbb4b..81fc633 100644 --- a/tests/DumpRenderTree2/Android.mk +++ b/tests/DumpRenderTree2/Android.mk @@ -1,3 +1,18 @@ +# +# 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. +# LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) diff --git a/tests/DumpRenderTree2/assets/run-apache2.py b/tests/DumpRenderTree2/assets/run-apache2.py new file mode 100644 index 0000000..cffbe37 --- /dev/null +++ b/tests/DumpRenderTree2/assets/run-apache2.py @@ -0,0 +1,107 @@ +#!/usr/bin/python +# +# 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. +# +"""Start, stop, or restart apache2 server. + + Apache2 must be installed with mod_php! + + Usage: + run-apache2.py start|stop|restart +""" + +import sys +import os +import subprocess +import logging + +def main(): + if len(sys.argv) < 2: + run_cmd = "" + else: + run_cmd = sys.argv[1] + + #Setup logging class + logging.basicConfig(level=logging.INFO, format='%(message)s') + + if not run_cmd in ("start", "stop", "restart"): + logging.info("illegal argument: " + run_cmd) + logging.info("Usage: python run-apache2.py start|stop|restart") + return + + #Create /tmp/WebKit if it doesn't exist. This is needed for various files used by apache2 + tmp_WebKit = os.path.join("/tmp", "WebKit") + if not os.path.exists(tmp_WebKit): + os.mkdir(tmp_WebKit) + + #Get the path to android tree root based on the script location. + #Basically we go 5 levels up + parent = os.pardir + script_location = os.path.abspath(os.path.dirname(sys.argv[0])) + android_tree_root = os.path.join(script_location, parent, parent, parent, parent, parent) + android_tree_root = os.path.normpath(android_tree_root) + + #Prepare the command to set ${APACHE_RUN_USER} and ${APACHE_RUN_GROUP} + envvars_path = os.path.join("/etc", "apache2", "envvars") + export_envvars_cmd = "source " + envvars_path + + error_log_path = os.path.join(tmp_WebKit, "apache2-error.log") + + #Prepare the command to (re)start/stop the server with specified settings + apache2_restart_cmd = "apache2 -k " + run_cmd + directives = " -c \"ServerRoot " + android_tree_root + "\"" + directives += " -c \"DocumentRoot " + os.path.join("external", "webkit") + "\"" + + #This directive is commented out in apache2-debian-httpd.conf for some reason + #However, it is useful to browse through tests in the browser, so it's added here. + #One thing to note is that because of problems with mod_dir and port numbers, mod_dir + #is turned off. That means that there _must_ be a trailing slash at the end of URL + #for auto indexes to work correctly. + directives += " -c \"LoadModule autoindex_module /usr/lib/apache2/modules/mod_autoindex.so\"" + + directives += " -c \"ErrorLog " + error_log_path +"\"" + directives += " -c \"SSLCertificateFile " + os.path.join ("external", "webkit", "LayoutTests", + "http", "conf", "webkit-httpd.pem") + "\"" + directives += " -c \"User ${APACHE_RUN_USER}\"" + directives += " -c \"Group ${APACHE_RUN_GROUP}\"" + directives += " -C \"TypesConfig " + os.path.join("/etc", "mime.types") + "\"" + conf_file_cmd = " -f " + os.path.join(android_tree_root, "external", "webkit", "LayoutTests", + "http", "conf", "apache2-debian-httpd.conf") + + #Try to execute the commands + logging.info("Will " + run_cmd + " apache2 server.") + cmd = export_envvars_cmd + " && " + apache2_restart_cmd + directives + conf_file_cmd + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (out, err) = p.communicate() + + #Output the stdout from the command to console + logging.info(out) + + #Report any errors + if p.returncode != 0: + logging.info("!! ERRORS:") + + if err.find(envvars_path) != -1: + logging.info(err) + elif err.find('command not found') != -1: + logging.info("apache2 is probably not installed") + else: + logging.info(err) + logging.info("Try looking in " + error_log_path + " for details") + else: + logging.info("OK") + +if __name__ == "__main__": + main(); diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index d6cfb12..e4f447e 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -1830,6 +1830,16 @@ ssize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir) continue; } + if (bundle->getMaxResVersion() != NULL && group.version.length() != 0) { + int maxResInt = atoi(bundle->getMaxResVersion()); + const char *verString = group.version.string(); + int dirVersionInt = atoi(verString + 1); // skip 'v' in version name + if (dirVersionInt > maxResInt) { + fprintf(stderr, "max res %d, skipping %s\n", maxResInt, entry->d_name); + continue; + } + } + FileType type = getFileType(subdirName.string()); if (type == kFileTypeDirectory) { diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index 3308a35..6a1f2d5 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -45,6 +45,7 @@ public: mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL), mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL), mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), + mMaxResVersion(NULL), mArgc(0), mArgv(NULL) {} ~Bundle(void) {} @@ -134,6 +135,8 @@ public: void setVersionName(const char* val) { mVersionName = val; } const char* getCustomPackage() const { return mCustomPackage; } void setCustomPackage(const char* val) { mCustomPackage = val; } + const char* getMaxResVersion() const { return mMaxResVersion; } + void setMaxResVersion(const char * val) { mMaxResVersion = val; } /* * Set and get the file specification. @@ -230,6 +233,7 @@ private: const char* mVersionCode; const char* mVersionName; const char* mCustomPackage; + const char* mMaxResVersion; /* file specification */ int mArgc; diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index b0c6e39..f457cc8 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -62,6 +62,7 @@ void usage(void) " [--rename-manifest-package PACKAGE] \\\n" " [--rename-instrumentation-target-package PACKAGE] \\\n" " [--utf16] [--auto-add-overlay] \\\n" + " [--max-res-version VAL] \\\n" " [-I base-package [-I base-package ...]] \\\n" " [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \\\n" " [-S resource-sources [-S resource-sources ...]] " @@ -128,6 +129,8 @@ void usage(void) " higher, the default encoding for resources will be in UTF-8.\n" " --target-sdk-version\n" " inserts android:targetSdkVersion in to manifest.\n" + " --max-res-version\n" + " ignores versioned resource directories above the given value.\n" " --values\n" " when used with \"dump resources\" also includes resource values.\n" " --version-code\n" @@ -416,6 +419,15 @@ int main(int argc, char* const argv[]) goto bail; } bundle.setMaxSdkVersion(argv[0]); + } else if (strcmp(cp, "-max-res-version") == 0) { + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '--max-res-version' option\n"); + wantUsage = true; + goto bail; + } + bundle.setMaxResVersion(argv[0]); } else if (strcmp(cp, "-version-code") == 0) { argc--; argv++; |
