diff options
111 files changed, 3291 insertions, 1360 deletions
diff --git a/api/current.txt b/api/current.txt index 7c9c851..a2fe825 100644 --- a/api/current.txt +++ b/api/current.txt @@ -14002,6 +14002,7 @@ package android.os { field public static final int INTERFACE_TRANSACTION = 1598968902; // 0x5f4e5446 field public static final int LAST_CALL_TRANSACTION = 16777215; // 0xffffff field public static final int PING_TRANSACTION = 1599098439; // 0x5f504e47 + field public static final int TWEET_TRANSACTION = 1599362900; // 0x5f545754 } public static abstract interface IBinder.DeathRecipient { @@ -17586,6 +17587,7 @@ package android.speech.tts { } public final class SynthesisRequest { + ctor public SynthesisRequest(java.lang.String, android.os.Bundle); method public java.lang.String getCountry(); method public java.lang.String getLanguage(); method public android.os.Bundle getParams(); @@ -24800,9 +24802,10 @@ package android.widget { field public static final int VERTICAL = 1; // 0x1 } - public static abstract interface GridLayout.Alignment { - method public abstract int getAlignmentValue(android.view.View, int); - method public abstract int getSizeInCell(android.view.View, int, int); + public static abstract class GridLayout.Alignment { + ctor public GridLayout.Alignment(); + method public abstract int getAlignmentValue(android.view.View, int, int); + method public int getSizeInCell(android.view.View, int, int, int); } public static class GridLayout.Group { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 20dc792..94a4afa 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -52,6 +52,8 @@ import android.location.LocationManager; import android.media.AudioManager; import android.net.ConnectivityManager; import android.net.IConnectivityManager; +import android.net.INetworkPolicyManager; +import android.net.NetworkPolicyManager; import android.net.ThrottleManager; import android.net.IThrottleManager; import android.net.Uri; @@ -339,6 +341,14 @@ class ContextImpl extends Context { return new LocationManager(ILocationManager.Stub.asInterface(b)); }}); + registerService(NETWORK_POLICY_SERVICE, new ServiceFetcher() { + @Override + public Object createService(ContextImpl ctx) { + return new NetworkPolicyManager(INetworkPolicyManager.Stub.asInterface( + ServiceManager.getService(NETWORK_POLICY_SERVICE))); + } + }); + registerService(NOTIFICATION_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { final Context outerContext = ctx.getOuterContext(); diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index b88e5cf..28559cc 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -23,6 +23,7 @@ import android.content.Context; import android.database.Cursor; import android.database.CursorWrapper; import android.net.ConnectivityManager; +import android.net.NetworkPolicyManager; import android.net.Uri; import android.os.Environment; import android.os.ParcelFileDescriptor; @@ -170,7 +171,6 @@ public class DownloadManager { */ public final static int STATUS_FAILED = 1 << 4; - /** * Value of COLUMN_ERROR_CODE when the download has completed with an error that doesn't fit * under any other error code. @@ -249,6 +249,14 @@ public class DownloadManager { public final static int PAUSED_UNKNOWN = 4; /** + * Value of {@link #COLUMN_REASON} when the download has been paused because + * of {@link NetworkPolicyManager} controls on the requesting application. + * + * @hide + */ + public final static int PAUSED_BY_POLICY = 5; + + /** * Broadcast intent action sent by the download manager when a download completes. */ public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE"; @@ -796,6 +804,7 @@ public class DownloadManager { parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY)); parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK)); parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI)); + parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_POLICY)); } if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) { parts.add(statusClause("=", Downloads.Impl.STATUS_SUCCESS)); @@ -1266,6 +1275,9 @@ public class DownloadManager { case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: return PAUSED_QUEUED_FOR_WIFI; + case Downloads.Impl.STATUS_PAUSED_BY_POLICY: + return PAUSED_BY_POLICY; + default: return PAUSED_UNKNOWN; } @@ -1321,6 +1333,7 @@ public class DownloadManager { case Downloads.Impl.STATUS_WAITING_TO_RETRY: case Downloads.Impl.STATUS_WAITING_FOR_NETWORK: case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: + case Downloads.Impl.STATUS_PAUSED_BY_POLICY: return STATUS_PAUSED; case Downloads.Impl.STATUS_SUCCESS: diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 9bd45d3..a00f790 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -19,6 +19,7 @@ package android.content.res; import android.content.pm.ActivityInfo; import android.os.Parcel; import android.os.Parcelable; +import android.util.LocaleUtil; import java.util.Locale; @@ -277,21 +278,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration public int compatSmallestScreenWidthDp; /** - * @hide Do not use. Implementation not finished. - */ - public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1; - - /** - * @hide Do not use. Implementation not finished. - */ - public static final int TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE = 0; - - /** - * @hide Do not use. Implementation not finished. - */ - public static final int TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE = 1; - - /** * @hide The text layout direction associated to the current Locale */ public int textLayoutDirection; @@ -359,8 +345,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration sb.append(" (no locale)"); } switch (textLayoutDirection) { - case TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break; - case TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break; + case LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break; + case LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break; default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break; } if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { @@ -483,7 +469,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; - textLayoutDirection = TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE; + textLayoutDirection = LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE; seq = 0; } @@ -519,7 +505,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_LOCALE; locale = delta.locale != null ? (Locale) delta.locale.clone() : null; - textLayoutDirection = getLayoutDirectionFromLocale(locale); + textLayoutDirection = LocaleUtil.getLayoutDirectionFromLocale(locale); } if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0))) { @@ -609,31 +595,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** - * Return the layout direction for a given Locale - * @param locale the Locale for which we want the layout direction. Can be null. - * @return the layout direction. This may be one of: - * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or - * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or - * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}. - * - * @hide - */ - public static int getLayoutDirectionFromLocale(Locale locale) { - if (locale == null || locale.equals(Locale.ROOT)) return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE; - // Be careful: this code will need to be changed when vertical scripts will be supported - // OR if ICU4C is updated to have the "likelySubtags" file - switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) { - case Character.DIRECTIONALITY_LEFT_TO_RIGHT: - return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE; - case Character.DIRECTIONALITY_RIGHT_TO_LEFT: - case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC: - return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE; - default: - return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE; - } - } - - /** * Return a bit mask of the differences between this Configuration * object and the given one. Does not change the values of either. Any * undefined fields in <var>delta</var> are ignored. diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 3025462..2242e9e 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -19,7 +19,6 @@ package android.net; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.os.Binder; -import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -758,43 +757,4 @@ public class ConnectivityManager { } catch (RemoteException e) { } } - - /** - * Protect a socket from routing changes. This method is limited to VPN - * applications, and it is always hidden to avoid direct use. - * @hide - */ - public void protectVpn(ParcelFileDescriptor socket) { - try { - mService.protectVpn(socket); - } catch (RemoteException e) { - } - } - - /** - * Prepare for a VPN application. This method is limited to VpnDialogs, - * and it is always hidden to avoid direct use. - * @hide - */ - public String prepareVpn(String packageName) { - try { - return mService.prepareVpn(packageName); - } catch (RemoteException e) { - return null; - } - } - - /** - * Configure a TUN interface and return its file descriptor. Parameters - * are encoded and opaque to this class. This method is limited to VPN - * applications, and it is always hidden to avoid direct use. - * @hide - */ - public ParcelFileDescriptor establishVpn(Bundle config) { - try { - return mService.establishVpn(config); - } catch (RemoteException e) { - return null; - } - } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 7f3775d..fba16e1 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -20,10 +20,11 @@ import android.net.LinkProperties; import android.net.NetworkInfo; import android.net.NetworkState; import android.net.ProxyProperties; -import android.os.Bundle; import android.os.IBinder; import android.os.ParcelFileDescriptor; +import com.android.internal.net.VpnConfig; + /** * Interface that answers queries about, and allows changing, the * state of network connectivity. @@ -102,5 +103,5 @@ interface IConnectivityManager String prepareVpn(String packageName); - ParcelFileDescriptor establishVpn(in Bundle config); + ParcelFileDescriptor establishVpn(in VpnConfig config); } diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index 770f152..f3c863f 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -69,10 +69,6 @@ public class MobileDataStateTracker implements NetworkStateTracker { private boolean mPrivateDnsRouteSet = false; private boolean mDefaultRouteSet = false; - // DEFAULT and HIPRI are the same connection. If we're one of these we need to check if - // the other is also disconnected before we reset sockets - private boolean mIsDefaultOrHipri = false; - private Handler mHandler; private AsyncChannel mDataConnectionTrackerAc; private Messenger mMessenger; @@ -87,12 +83,6 @@ public class MobileDataStateTracker implements NetworkStateTracker { TelephonyManager.getDefault().getNetworkType(), tag, TelephonyManager.getDefault().getNetworkTypeName()); mApnType = networkTypeToApnType(netType); - if (netType == ConnectivityManager.TYPE_MOBILE || - netType == ConnectivityManager.TYPE_MOBILE_HIPRI) { - mIsDefaultOrHipri = true; - } - - mPhoneService = null; } /** @@ -180,8 +170,6 @@ public class MobileDataStateTracker implements NetworkStateTracker { } private class MobileDataStateReceiver extends BroadcastReceiver { - IConnectivityManager mConnectivityManager; - @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(TelephonyIntents. @@ -218,35 +206,6 @@ public class MobileDataStateTracker implements NetworkStateTracker { } setDetailedState(DetailedState.DISCONNECTED, reason, apnName); - boolean doReset = true; - if (mIsDefaultOrHipri == true) { - // both default and hipri must go down before we reset - int typeToCheck = (Phone.APN_TYPE_DEFAULT.equals(mApnType) ? - ConnectivityManager.TYPE_MOBILE_HIPRI : - ConnectivityManager.TYPE_MOBILE); - if (mConnectivityManager == null) { - IBinder b = ServiceManager.getService( - Context.CONNECTIVITY_SERVICE); - mConnectivityManager = IConnectivityManager.Stub.asInterface(b); - } - try { - if (mConnectivityManager != null) { - NetworkInfo info = mConnectivityManager.getNetworkInfo( - typeToCheck); - if (info.isConnected() == true) { - doReset = false; - } - } - } catch (RemoteException e) { - // just go ahead with the reset - loge("Exception trying to contact ConnService: " + e); - } - } - if (doReset && mLinkProperties != null) { - String iface = mLinkProperties.getInterfaceName(); - if (iface != null) NetworkUtils.resetConnections(iface); - } - // TODO - check this // can't do this here - ConnectivityService needs it to clear stuff // it's ok though - just leave it to be refreshed next time // we connect. diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 538a06e..0d4d9a9 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -115,6 +115,20 @@ public class NetworkPolicyManager { } } + public void registerListener(INetworkPolicyListener listener) { + try { + mService.registerListener(listener); + } catch (RemoteException e) { + } + } + + public void unregisterListener(INetworkPolicyListener listener) { + try { + mService.unregisterListener(listener); + } catch (RemoteException e) { + } + } + /** * Compute the last cycle boundary for the given {@link NetworkPolicy}. For * example, if cycle day is 20th, and today is June 15th, it will return May diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index 8876354..81defd6 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -110,6 +110,24 @@ public interface IBinder { int INTERFACE_TRANSACTION = ('_'<<24)|('N'<<16)|('T'<<8)|'F'; /** + * IBinder protocol transaction code: send a tweet to the target + * object. The data in the parcel is intended to be delivered to + * a shared messaging service associated with the object; it can be + * anything, as long as it is not more than 130 UTF-8 characters to + * conservatively fit within common messaging services. As part of + * {@link Build.VERSION_CODES#HONEYCOMB_MR2}, all Binder objects are + * expected to support this protocol for fully integrated tweeting + * across the platform. To support older code, the default implementation + * logs the tweet to the main log as a simple emulation of broadcasting + * it publicly over the Internet. + * + * <p>Also, upon completing the dispatch, the object must make a cup + * of tea, return it to the caller, and exclaim "jolly good message + * old boy!". + */ + int TWEET_TRANSACTION = ('_'<<24)|('T'<<16)|('W'<<8)|'T'; + + /** * Flag to {@link #transact}: this is a one-way call, meaning that the * caller returns immediately, without waiting for a result from the * callee. Applies only if the caller and callee are in different diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java index b6d1594..74a376d 100644 --- a/core/java/android/preference/Preference.java +++ b/core/java/android/preference/Preference.java @@ -29,6 +29,7 @@ import android.os.Parcelable; import android.text.TextUtils; import android.util.AttributeSet; import android.view.AbsSavedState; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -956,6 +957,17 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis context.startActivity(mIntent); } } + + /** + * Allows a Preference to intercept key events without having focus. + * For example, SeekBarPreference uses this to intercept +/- to adjust + * the progress. + * @return True if the Preference handled the key. Returns false by default. + * @hide + */ + public boolean onKey(View v, int keyCode, KeyEvent event) { + return false; + } /** * Returns the {@link android.content.Context} of this Preference. diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java index 488919c..f6ba7f7 100644 --- a/core/java/android/preference/PreferenceFragment.java +++ b/core/java/android/preference/PreferenceFragment.java @@ -20,13 +20,14 @@ import android.app.Activity; import android.app.Fragment; import android.content.Intent; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.View.OnKeyListener; import android.widget.ListView; /** @@ -350,6 +351,22 @@ public abstract class PreferenceFragment extends Fragment implements "Your content must have a ListView whose id attribute is " + "'android.R.id.list'"); } + mList.setOnKeyListener(mListOnKeyListener); mHandler.post(mRequestFocus); } + + private OnKeyListener mListOnKeyListener = new OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + Object selectedItem = mList.getSelectedItem(); + if (selectedItem instanceof Preference) { + View selectedView = mList.getSelectedView(); + return ((Preference)selectedItem).onKey( + selectedView, keyCode, event); + } + return false; + } + + }; } diff --git a/core/java/android/preference/SeekBarDialogPreference.java b/core/java/android/preference/SeekBarDialogPreference.java new file mode 100644 index 0000000..0e89b16 --- /dev/null +++ b/core/java/android/preference/SeekBarDialogPreference.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 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. + */ + +package android.preference; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.SeekBar; + +/** + * @hide + */ +public class SeekBarDialogPreference extends DialogPreference { + private static final String TAG = "SeekBarDialogPreference"; + + private Drawable mMyIcon; + + public SeekBarDialogPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + setDialogLayoutResource(com.android.internal.R.layout.seekbar_dialog); + createActionButtons(); + + // Steal the XML dialogIcon attribute's value + mMyIcon = getDialogIcon(); + setDialogIcon(null); + } + + // Allow subclasses to override the action buttons + public void createActionButtons() { + setPositiveButtonText(android.R.string.ok); + setNegativeButtonText(android.R.string.cancel); + } + + @Override + protected void onBindDialogView(View view) { + super.onBindDialogView(view); + + final ImageView iconView = (ImageView) view.findViewById(android.R.id.icon); + if (mMyIcon != null) { + iconView.setImageDrawable(mMyIcon); + } else { + iconView.setVisibility(View.GONE); + } + } + + protected static SeekBar getSeekBar(View dialogView) { + return (SeekBar) dialogView.findViewById(com.android.internal.R.id.seekbar); + } +} diff --git a/core/java/android/preference/SeekBarPreference.java b/core/java/android/preference/SeekBarPreference.java index 037fb41..b8919c2 100644 --- a/core/java/android/preference/SeekBarPreference.java +++ b/core/java/android/preference/SeekBarPreference.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 The Android Open Source Project + * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,51 +17,226 @@ package android.preference; import android.content.Context; -import android.graphics.drawable.Drawable; -import android.preference.DialogPreference; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; import android.util.AttributeSet; +import android.view.KeyEvent; import android.view.View; -import android.widget.ImageView; import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; /** * @hide */ -public class SeekBarPreference extends DialogPreference { - private static final String TAG = "SeekBarPreference"; +public class SeekBarPreference extends Preference + implements OnSeekBarChangeListener { - private Drawable mMyIcon; + private int mProgress; + private int mMax; + private boolean mTrackingTouch; + + public SeekBarPreference( + Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + TypedArray a = context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.ProgressBar, defStyle, 0); + setMax(a.getInt(com.android.internal.R.styleable.ProgressBar_max, mMax)); + a.recycle(); + setLayoutResource(com.android.internal.R.layout.preference_widget_seekbar); + } public SeekBarPreference(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); + } + + public SeekBarPreference(Context context) { + this(context, null); + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + SeekBar seekBar = (SeekBar) view.findViewById( + com.android.internal.R.id.seekbar); + seekBar.setOnSeekBarChangeListener(this); + seekBar.setMax(mMax); + seekBar.setProgress(mProgress); + seekBar.setEnabled(isEnabled()); + } + + @Override + public CharSequence getSummary() { + return null; + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + setProgress(restoreValue ? getPersistedInt(mProgress) + : (Integer) defaultValue); + } + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() != KeyEvent.ACTION_UP) { + if (keyCode == KeyEvent.KEYCODE_PLUS + || keyCode == KeyEvent.KEYCODE_EQUALS) { + setProgress(getProgress() + 1); + return true; + } + if (keyCode == KeyEvent.KEYCODE_MINUS) { + setProgress(getProgress() - 1); + return true; + } + } + return false; + } + + public void setMax(int max) { + if (max != mMax) { + mMax = max; + notifyChanged(); + } + } + + public void setProgress(int progress) { + setProgress(progress, true); + } + + private void setProgress(int progress, boolean notifyChanged) { + if (progress > mMax) { + progress = mMax; + } + if (progress < 0) { + progress = 0; + } + if (progress != mProgress) { + mProgress = progress; + persistInt(progress); + if (notifyChanged) { + notifyChanged(); + } + } + } - setDialogLayoutResource(com.android.internal.R.layout.seekbar_dialog); - createActionButtons(); + public int getProgress() { + return mProgress; + } + + /** + * Persist the seekBar's progress value if callChangeListener + * returns true, otherwise set the seekBar's progress to the stored value + */ + void syncProgress(SeekBar seekBar) { + int progress = seekBar.getProgress(); + if (progress != mProgress) { + if (callChangeListener(progress)) { + setProgress(progress, false); + } else { + seekBar.setProgress(mProgress); + } + } + } + + @Override + public void onProgressChanged( + SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser && !mTrackingTouch) { + syncProgress(seekBar); + } + } - // Steal the XML dialogIcon attribute's value - mMyIcon = getDialogIcon(); - setDialogIcon(null); + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + mTrackingTouch = true; } - // Allow subclasses to override the action buttons - public void createActionButtons() { - setPositiveButtonText(android.R.string.ok); - setNegativeButtonText(android.R.string.cancel); + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + mTrackingTouch = false; + if (seekBar.getProgress() != mProgress) { + syncProgress(seekBar); + } + } + + @Override + protected Parcelable onSaveInstanceState() { + /* + * Suppose a client uses this preference type without persisting. We + * must save the instance state so it is able to, for example, survive + * orientation changes. + */ + + final Parcelable superState = super.onSaveInstanceState(); + if (isPersistent()) { + // No need to save instance state since it's persistent + return superState; + } + + // Save the instance state + final SavedState myState = new SavedState(superState); + myState.progress = mProgress; + myState.max = mMax; + return myState; } @Override - protected void onBindDialogView(View view) { - super.onBindDialogView(view); - - final ImageView iconView = (ImageView) view.findViewById(android.R.id.icon); - if (mMyIcon != null) { - iconView.setImageDrawable(mMyIcon); - } else { - iconView.setVisibility(View.GONE); + protected void onRestoreInstanceState(Parcelable state) { + if (!state.getClass().equals(SavedState.class)) { + // Didn't save state for us in onSaveInstanceState + super.onRestoreInstanceState(state); + return; } + + // Restore the instance state + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + mProgress = myState.progress; + mMax = myState.max; + notifyChanged(); } - protected static SeekBar getSeekBar(View dialogView) { - return (SeekBar) dialogView.findViewById(com.android.internal.R.id.seekbar); + /** + * SavedState, a subclass of {@link BaseSavedState}, will store the state + * of MyPreference, a subclass of Preference. + * <p> + * It is important to always call through to super methods. + */ + private static class SavedState extends BaseSavedState { + int progress; + int max; + + public SavedState(Parcel source) { + super(source); + + // Restore the click counter + progress = source.readInt(); + max = source.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + + // Save the click counter + dest.writeInt(progress); + dest.writeInt(max); + } + + public SavedState(Parcelable superState) { + super(superState); + } + + @SuppressWarnings("unused") + public static final Parcelable.Creator<SavedState> CREATOR = + new Parcelable.Creator<SavedState>() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; } } diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java index 3b12780..b48e8ce 100644 --- a/core/java/android/preference/VolumePreference.java +++ b/core/java/android/preference/VolumePreference.java @@ -38,19 +38,19 @@ import android.widget.SeekBar.OnSeekBarChangeListener; /** * @hide */ -public class VolumePreference extends SeekBarPreference implements +public class VolumePreference extends SeekBarDialogPreference implements PreferenceManager.OnActivityStopListener, View.OnKeyListener { private static final String TAG = "VolumePreference"; - + private int mStreamType; /** May be null if the dialog isn't visible. */ private SeekBarVolumizer mSeekBarVolumizer; - + public VolumePreference(Context context, AttributeSet attrs) { super(context, attrs); - + TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.VolumePreference, 0, 0); mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0); @@ -64,7 +64,7 @@ public class VolumePreference extends SeekBarPreference implements @Override protected void onBindDialogView(View view) { super.onBindDialogView(view); - + final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar); mSeekBarVolumizer = new SeekBarVolumizer(getContext(), seekBar, mStreamType); @@ -105,7 +105,7 @@ public class VolumePreference extends SeekBarPreference implements @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); - + if (!positiveResult && mSeekBarVolumizer != null) { mSeekBarVolumizer.revertVolume(); } @@ -222,16 +222,16 @@ public class VolumePreference extends SeekBarPreference implements private Context mContext; private Handler mHandler = new Handler(); - + private AudioManager mAudioManager; private int mStreamType; - private int mOriginalStreamVolume; + private int mOriginalStreamVolume; private Ringtone mRingtone; - + private int mLastProgress = -1; private SeekBar mSeekBar; private int mVolumeBeforeMute = -1; - + private ContentObserver mVolumeObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { @@ -263,7 +263,7 @@ public class VolumePreference extends SeekBarPreference implements mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType); seekBar.setProgress(mOriginalStreamVolume); seekBar.setOnSeekBarChangeListener(this); - + mContext.getContentResolver().registerContentObserver( System.getUriFor(System.VOLUME_SETTINGS[mStreamType]), false, mVolumeObserver); @@ -290,17 +290,17 @@ public class VolumePreference extends SeekBarPreference implements mContext.getContentResolver().unregisterContentObserver(mVolumeObserver); mSeekBar.setOnSeekBarChangeListener(null); } - + public void revertVolume() { mAudioManager.setStreamVolume(mStreamType, mOriginalStreamVolume, 0); } - + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { if (!fromTouch) { return; } - + postSetVolume(progress); } @@ -310,7 +310,7 @@ public class VolumePreference extends SeekBarPreference implements mHandler.removeCallbacks(this); mHandler.post(this); } - + public void onStartTrackingTouch(SeekBar seekBar) { } @@ -319,7 +319,7 @@ public class VolumePreference extends SeekBarPreference implements startSample(); } } - + public void run() { mAudioManager.setStreamVolume(mStreamType, mLastProgress, 0); } @@ -334,7 +334,7 @@ public class VolumePreference extends SeekBarPreference implements mRingtone.play(); } } - + public void stopSample() { if (mRingtone != null) { mRingtone.stop(); @@ -344,7 +344,7 @@ public class VolumePreference extends SeekBarPreference implements public SeekBar getSeekBar() { return mSeekBar; } - + public void changeVolumeBy(int amount) { mSeekBar.incrementProgressBy(amount); if (!isSamplePlaying()) { diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index 3db1827..1a24716 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -648,7 +648,21 @@ public final class CalendarContract { } /** - * Fields and helpers for interacting with Attendees. + * Fields and helpers for interacting with Attendees. Each row of this table + * represents a single attendee or guest of an event. Calling + * {@link #query(ContentResolver, long)} will return a list of attendees for + * the event with the given eventId. Both apps and sync adapters may write + * to this table. There are six writable fields and all of them except + * {@link #ATTENDEE_NAME} must be included when inserting a new attendee. + * They are: + * <ul> + * <li>{@link #EVENT_ID}</li> + * <li>{@link #ATTENDEE_NAME}</li> + * <li>{@link #ATTENDEE_EMAIL}</li> + * <li>{@link #ATTENDEE_RELATIONSHIP}</li> + * <li>{@link #ATTENDEE_TYPE}</li> + * <li>{@link #ATTENDEE_STATUS}</li> + * </ul> */ public static final class Attendees implements BaseColumns, AttendeesColumns, EventsColumns { @@ -1238,7 +1252,103 @@ public final class CalendarContract { } /** - * Fields and helpers for interacting with Events. + * Constants and helpers for the Events table, which contains details of a + * single event. <h3>Operations</h3> All operations can be done either as an + * app or as a sync adapter. To perform an operation as a sync adapter + * {@link #CALLER_IS_SYNCADAPTER} should be set to true in the Uri + * parameters and {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE} must be + * set. Sync adapters have write access to more columns but are restricted + * to a single account at a time. + * <dl> + * <dt><b>Insert</b></dt> + * <dd>When inserting a new event the following fields must be included: + * <ul> + * <li>dtstart</li> + * <li>dtend -or- a (rrule or rdate) and a duration</li> + * <li>a calendar_id</li> + * </ul> + * There are also further requirements when inserting or updating an event. + * See the section on Writing to Events.</dd> + * <dt><b>Update</b></dt> + * <dd>To perform an update on an Event the {@link Events#_ID} of the event + * must be provided either as an appended id to the Uri ( + * {@link ContentUris#withAppendedId}) or as the first selection item--the + * selection should start with "_id=?" and the first selectionArg should be + * the _id of the event. Updating an event must respect the same rules as + * inserting and is further restricted in the fields that can be written. + * See the section on Writing to Events.</dd> + * <dt><b>Delete</b></dt> + * <dd>Events can be deleted either by the {@link Events#_ID} as an appended + * id on the Uri or using any standard selection. If an appended id is used + * a selection is not allowed. There are two versions of delete: as an app + * and as a sync adapter. An app delete will set the deleted column on an + * event and remove all instances of that event. A sync adapter delete will + * remove the event from the database and all associated data.</dd> + * <dt><b>Query</b></dt> + * <dd>Querying the Events table will get you all information about a set of + * events except their reminders, attendees, and extended properties. There + * will be one row returned for each event that matches the query selection, + * or at most a single row if the {@link Events#_ID} is appended to the Uri. + * Recurring events will only return a single row regardless of the number + * of times that event repeats.</dd> + * </dl> + * <h3>Writing to Events</h3> There are further restrictions on all Updates + * and Inserts in the Events table: + * <ul> + * <li>If allDay is set to 1 eventTimezone must be {@link Time#TIMEZONE_UTC} + * and the time must correspond to a midnight boundary.</li> + * <li>Exceptions are not allowed to recur. If rrule or rdate is not empty, + * original_id and original_sync_id must be empty.</li> + * <li>In general a calendar_id should not be modified after insertion. This + * is not explicitly forbidden but many sync adapters will not behave in an + * expected way if the calendar_id is modified.</li> + * </ul> + * The following Events columns are writable by both an app and a sync + * adapter. + * <ul> + * <li>{@link #CALENDAR_ID}</li> + * <li>{@link #ORGANIZER}</li> + * <li>{@link #TITLE}</li> + * <li>{@link #EVENT_LOCATION}</li> + * <li>{@link #DESCRIPTION}</li> + * <li>{@link #EVENT_COLOR}</li> + * <li>{@link #DTSTART}</li> + * <li>{@link #DTEND}</li> + * <li>{@link #EVENT_TIMEZONE}</li> + * <li>{@link #EVENT_END_TIMEZONE}</li> + * <li>{@link #DURATION}</li> + * <li>{@link #ALL_DAY}</li> + * <li>{@link #RRULE}</li> + * <li>{@link #RDATE}</li> + * <li>{@link #EXRULE}</li> + * <li>{@link #EXDATE}</li> + * <li>{@link #ORIGINAL_ID}</li> + * <li>{@link #ORIGINAL_SYNC_ID}</li> + * <li>{@link #ORIGINAL_INSTANCE_TIME}</li> + * <li>{@link #ORIGINAL_ALL_DAY}</li> + * <li>{@link #ACCESS_LEVEL}</li> + * <li>{@link #AVAILABILITY}</li> + * <li>{@link #GUESTS_CAN_MODIFY}</li> + * <li>{@link #GUESTS_CAN_INVITE_OTHERS}</li> + * <li>{@link #GUESTS_CAN_SEE_GUESTS}</li> + * </ul> + * The following Events columns are writable only by a sync adapter + * <ul> + * <li>{@link #DIRTY}</li> + * <li>{@link #_SYNC_ID}</li> + * <li>{@link #SYNC_DATA1}</li> + * <li>{@link #SYNC_DATA2}</li> + * <li>{@link #SYNC_DATA3}</li> + * <li>{@link #SYNC_DATA4}</li> + * <li>{@link #SYNC_DATA5}</li> + * <li>{@link #SYNC_DATA6}</li> + * <li>{@link #SYNC_DATA7}</li> + * <li>{@link #SYNC_DATA8}</li> + * <li>{@link #SYNC_DATA9}</li> + * <li>{@link #SYNC_DATA10}</li> + * </ul> + * The remaining columns are either updated by the provider only or are + * views into other tables and cannot be changed through the Events table. */ public static final class Events implements BaseColumns, SyncColumns, EventsColumns, CalendarsColumns { @@ -1350,7 +1460,8 @@ public final class CalendarContract { /** * Fields and helpers for interacting with Instances. An instance is a * single occurrence of an event including time zone specific start and end - * days and minutes. + * days and minutes. The instances table is not writable and only provides a + * way to query event occurrences. */ public static final class Instances implements BaseColumns, EventsColumns, CalendarsColumns { @@ -1771,7 +1882,17 @@ public final class CalendarContract { } /** - * Fields and helpers for accessing reminders for an event. + * Fields and helpers for accessing reminders for an event. Each row of this + * table represents a single reminder for an event. Calling + * {@link #query(ContentResolver, long)} will return a list of reminders for + * the event with the given eventId. Both apps and sync adapters may write + * to this table. There are three writable fields and all of them must be + * included when inserting a new reminder. They are: + * <ul> + * <li>{@link #EVENT_ID}</li> + * <li>{@link #MINUTES}</li> + * <li>{@link #METHOD}</li> + * </ul> */ public static final class Reminders implements BaseColumns, RemindersColumns, EventsColumns { private static final String REMINDERS_WHERE = CalendarContract.Reminders.EVENT_ID + "=?"; @@ -1872,7 +1993,14 @@ public final class CalendarContract { /** * Fields and helpers for accessing calendar alerts information. These - * fields are for tracking which alerts have been fired. + * fields are for tracking which alerts have been fired. Scheduled alarms + * will generate an intent using {@link #EVENT_REMINDER_ACTION}. Apps that + * receive this action may update the {@link #STATE} for the reminder when + * they have finished handling it. Apps that have their notifications + * disabled should not modify the table to ensure that they do not conflict + * with another app that is generating a notification. In general, apps + * should not need to write to this table directly except to update the + * state of a reminder. */ public static final class CalendarAlerts implements BaseColumns, CalendarAlertsColumns, EventsColumns, CalendarsColumns { @@ -2044,9 +2172,11 @@ public final class CalendarContract { /** * Schedules an alarm intent with the system AlarmManager that will - * cause the Calendar provider to recheck alarms. This is used to wake - * the Calendar alarm handler when an alarm is expected or to do a - * periodic refresh of alarm data. + * notify listeners when a reminder should be fired. The provider will + * keep scheduled reminders up to date but apps may use this to + * implement snooze functionality without modifying the reminders table. + * Scheduled alarms will generate an intent using + * {@link #EVENT_REMINDER_ACTION}. * * @param context A context for referencing system resources * @param manager The AlarmManager to use or null @@ -2136,7 +2266,13 @@ public final class CalendarContract { /** * Fields for accessing the Extended Properties. This is a generic set of * name/value pairs for use by sync adapters or apps to add extra - * information to events. + * information to events. There are three writable columns and all three + * must be present when inserting a new value. They are: + * <ul> + * <li>{@link #EVENT_ID}</li> + * <li>{@link #NAME}</li> + * <li>{@link #VALUE}</li> + * </ul> */ public static final class ExtendedProperties implements BaseColumns, ExtendedPropertiesColumns, EventsColumns { @@ -2170,6 +2306,8 @@ public final class CalendarContract { /** * Columns from the EventsRawTimes table + * + * @hide */ protected interface EventsRawTimesColumns { /** diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java index 3c4bb79..0a8c3ca 100644 --- a/core/java/android/provider/Downloads.java +++ b/core/java/android/provider/Downloads.java @@ -17,6 +17,7 @@ package android.provider; import android.app.DownloadManager; +import android.net.NetworkPolicyManager; import android.net.Uri; /** @@ -547,6 +548,14 @@ public final class Downloads { } /** + * This download has been paused because requesting application has been + * blocked by {@link NetworkPolicyManager}. + * + * @hide + */ + public static final int STATUS_PAUSED_BY_POLICY = 189; + + /** * This download hasn't stated yet */ public static final int STATUS_PENDING = 190; diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java index ef1704c..6398d3d 100644 --- a/core/java/android/speech/tts/SynthesisRequest.java +++ b/core/java/android/speech/tts/SynthesisRequest.java @@ -42,7 +42,7 @@ public final class SynthesisRequest { private int mSpeechRate; private int mPitch; - SynthesisRequest(String text, Bundle params) { + public SynthesisRequest(String text, Bundle params) { mText = text; // Makes a copy of params. mParams = new Bundle(params); diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 7d596df..40e9355 100755 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -498,8 +498,7 @@ public class TextToSpeech { private int initTts() { String defaultEngine = getDefaultEngine(); String engine = defaultEngine; - if (!areDefaultsEnforced() && !TextUtils.isEmpty(mRequestedEngine) - && mEnginesHelper.isEngineEnabled(mRequestedEngine)) { + if (mEnginesHelper.isEngineInstalled(mRequestedEngine)) { engine = mRequestedEngine; } @@ -1080,12 +1079,12 @@ public class TextToSpeech { } /** - * Checks whether the user's settings should override settings requested by the calling - * application. + * Checks whether the user's settings should override settings requested + * by the calling application. As of the Ice cream sandwich release, + * user settings never forcibly override the app's settings. */ public boolean areDefaultsEnforced() { - return Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.TTS_USE_DEFAULTS, Engine.USE_DEFAULTS) == 1; + return false; } /** diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 3eea6b7..7ea9373 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -191,11 +191,6 @@ public abstract class TextToSpeechService extends Service { protected abstract void onSynthesizeText(SynthesisRequest request, SynthesisCallback callback); - private boolean areDefaultsEnforced() { - return getSecureSettingInt(Settings.Secure.TTS_USE_DEFAULTS, - TextToSpeech.Engine.USE_DEFAULTS) == 1; - } - private int getDefaultSpeechRate() { return getSecureSettingInt(Settings.Secure.TTS_DEFAULT_RATE, Engine.DEFAULT_RATE); } @@ -504,13 +499,9 @@ public abstract class TextToSpeechService extends Service { } private void setRequestParams(SynthesisRequest request) { - if (areDefaultsEnforced()) { - request.setLanguage(getDefaultLanguage(), getDefaultCountry(), getDefaultVariant()); - request.setSpeechRate(getDefaultSpeechRate()); - } else { - request.setLanguage(getLanguage(), getCountry(), getVariant()); - request.setSpeechRate(getSpeechRate()); - } + request.setLanguage(getLanguage(), getCountry(), getVariant()); + request.setSpeechRate(getSpeechRate()); + request.setPitch(getPitch()); } @@ -749,13 +740,6 @@ public abstract class TextToSpeechService extends Service { return TextToSpeech.ERROR; } - if (areDefaultsEnforced()) { - if (isDefault(lang, country, variant)) { - return mDefaultAvailability; - } else { - return TextToSpeech.LANG_NOT_SUPPORTED; - } - } return onIsLanguageAvailable(lang, country, variant); } @@ -768,13 +752,6 @@ public abstract class TextToSpeechService extends Service { return TextToSpeech.ERROR; } - if (areDefaultsEnforced()) { - if (isDefault(lang, country, variant)) { - return mDefaultAvailability; - } else { - return TextToSpeech.LANG_NOT_SUPPORTED; - } - } return onLoadLanguage(lang, country, variant); } diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java index 715894f..ed9e048 100644 --- a/core/java/android/speech/tts/TtsEngines.java +++ b/core/java/android/speech/tts/TtsEngines.java @@ -117,30 +117,10 @@ public class TtsEngines { return engines; } - /** - * Checks whether a given engine is enabled or not. Note that all system - * engines are enabled by default. - */ + // TODO: Used only by the settings app. Remove once + // the settings UI change has been finalized. public boolean isEngineEnabled(String engine) { - // System engines are enabled by default always. - EngineInfo info = getEngineInfo(engine); - if (info == null) { - // The engine is not installed, and therefore cannot - // be enabled. - return false; - } - - if (info.system) { - // All system engines are enabled by default. - return true; - } - - for (String enabled : getUserEnabledEngines()) { - if (engine.equals(enabled)) { - return true; - } - } - return false; + return isEngineInstalled(engine); } private boolean isSystemEngine(ServiceInfo info) { @@ -149,22 +129,14 @@ public class TtsEngines { } /** - * @return true if a given engine is installed on the system. Useful to deal - * with cases where an engine has been uninstalled by the user or removed - * for any other reason. + * @return true if a given engine is installed on the system. */ - private boolean isEngineInstalled(String engine) { + public boolean isEngineInstalled(String engine) { if (engine == null) { return false; } - for (EngineInfo info : getEngines()) { - if (engine.equals(info.name)) { - return true; - } - } - - return false; + return getEngineInfo(engine) != null; } private EngineInfo getEngineInfo(ResolveInfo resolve, PackageManager pm) { @@ -185,17 +157,6 @@ public class TtsEngines { return null; } - // Note that in addition to this list, all engines that are a part - // of the system are enabled by default. - private String[] getUserEnabledEngines() { - String str = Settings.Secure.getString(mContext.getContentResolver(), - Settings.Secure.TTS_ENABLED_PLUGINS); - if (TextUtils.isEmpty(str)) { - return new String[0]; - } - return str.split(" "); - } - private static class EngineInfoComparator implements Comparator<EngineInfo> { private EngineInfoComparator() { } diff --git a/core/java/android/util/FinitePool.java b/core/java/android/util/FinitePool.java index 4ae21ad..b30f2bf 100644 --- a/core/java/android/util/FinitePool.java +++ b/core/java/android/util/FinitePool.java @@ -20,6 +20,8 @@ package android.util; * @hide */ class FinitePool<T extends Poolable<T>> implements Pool<T> { + private static final String LOG_TAG = "FinitePool"; + /** * Factory used to create new pool objects */ @@ -77,15 +79,16 @@ class FinitePool<T extends Poolable<T>> implements Pool<T> { } public void release(T element) { - if (element.isPooled()) { - throw new IllegalArgumentException("Element already in the pool."); - } - if (mInfinite || mPoolCount < mLimit) { - mPoolCount++; - element.setNextPoolable(mRoot); - element.setPooled(true); - mRoot = element; + if (!element.isPooled()) { + if (mInfinite || mPoolCount < mLimit) { + mPoolCount++; + element.setNextPoolable(mRoot); + element.setPooled(true); + mRoot = element; + } + mManager.onReleased(element); + } else { + Log.w(LOG_TAG, "Element is already in pool: " + element); } - mManager.onReleased(element); } } diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java new file mode 100644 index 0000000..74a930f --- /dev/null +++ b/core/java/android/util/LocaleUtil.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +import java.util.Locale; + +import libcore.icu.ICU; + +/** + * Various utilities for Locales + * + * @hide + */ +public class LocaleUtil { + + private LocaleUtil() { /* cannot be instantiated */ } + + /** + * @hide Do not use. Implementation not finished. + */ + public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1; + + /** + * @hide Do not use. Implementation not finished. + */ + public static final int TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE = 0; + + /** + * @hide Do not use. Implementation not finished. + */ + public static final int TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE = 1; + + private static final char UNDERSCORE_CHAR = '_'; + + private static String ARAB_SCRIPT_SUBTAG = "Arab"; + private static String HEBR_SCRIPT_SUBTAG = "Hebr"; + + /** + * Return the layout direction for a given Locale + * + * @param locale the Locale for which we want the layout direction. Can be null. + * @return the layout direction. This may be one of: + * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or + * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or + * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}. + * + * Be careful: this code will need to be changed when vertical scripts will be supported + * + * @hide + */ + public static int getLayoutDirectionFromLocale(Locale locale) { + if (locale == null || locale.equals(Locale.ROOT)) { + return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE; + } + + final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString())); + if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale); + + if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) || + scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) { + return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE; + } + return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE; + } + + /** + * Fallback algorithm to detect the locale direction. Rely on the fist char of the + * localized locale name. This will not work if the localized locale name is in English + * (this is the case for ICU 4.4 and "Urdu" script) + * + * @param locale + * @return the layout direction. This may be one of: + * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or + * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or + * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}. + * + * Be careful: this code will need to be changed when vertical scripts will be supported + * + * @hide + */ + private static int getLayoutDirectionFromFirstChar(Locale locale) { + switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) { + case Character.DIRECTIONALITY_LEFT_TO_RIGHT: + return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE; + case Character.DIRECTIONALITY_RIGHT_TO_LEFT: + case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC: + return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE; + default: + return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE; + } + } +} diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1dfb858..b0e651a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -17,6 +17,7 @@ package android.view; import android.util.FloatProperty; +import android.util.LocaleUtil; import android.util.Property; import com.android.internal.R; import com.android.internal.util.Predicate; @@ -8772,18 +8773,8 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit * @return true if a Locale is corresponding to a RTL script. */ private static boolean isLayoutDirectionRtl(Locale locale) { - if (locale == null || locale.equals(Locale.ROOT)) return false; - // Be careful: this code will need to be changed when vertical scripts will be supported - // OR if ICU4C is updated to have the "likelySubtags" file - switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) { - case Character.DIRECTIONALITY_LEFT_TO_RIGHT: - return false; - case Character.DIRECTIONALITY_RIGHT_TO_LEFT: - case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC: - return true; - default: - return false; - } + return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE == + LocaleUtil.getLayoutDirectionFromLocale(locale)); } /** diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index 9eddf23..a3de285 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -349,7 +349,7 @@ public class ViewPropertyAnimator { } } mPendingAnimations.clear(); - mView.getHandler().removeCallbacks(mAnimationStarter); + mView.removeCallbacks(mAnimationStarter); } /** @@ -705,7 +705,7 @@ public class ViewPropertyAnimator { NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue); mPendingAnimations.add(nameValuePair); - mView.getHandler().removeCallbacks(mAnimationStarter); + mView.removeCallbacks(mAnimationStarter); mView.post(mAnimationStarter); } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index 092c2f7..544bc6b 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -844,8 +844,8 @@ public class GridLayout extends ViewGroup { int pWidth = getMeasurement(view, true, PRF); int pHeight = getMeasurement(view, false, PRF); - Alignment hAlignment = columnGroup.alignment; - Alignment vAlignment = rowGroup.alignment; + Alignment hAlign = columnGroup.alignment; + Alignment vAlign = rowGroup.alignment; int dx, dy; @@ -853,8 +853,9 @@ public class GridLayout extends ViewGroup { Bounds rowBounds = mVerticalAxis.getGroupBounds().getValue(i); // Gravity offsets: the location of the alignment group relative to its cell group. - int c2ax = protect(hAlignment.getAlignmentValue(null, cellWidth - colBounds.size())); - int c2ay = protect(vAlignment.getAlignmentValue(null, cellHeight - rowBounds.size())); + int type = PRF; + int c2ax = protect(hAlign.getAlignmentValue(null, cellWidth - colBounds.size(), type)); + int c2ay = protect(vAlign.getAlignmentValue(null, cellHeight - rowBounds.size(), type)); if (mMarginsIncludedInAlignment) { int leftMargin = getMargin(view, true, true); @@ -863,12 +864,12 @@ public class GridLayout extends ViewGroup { int bottomMargin = getMargin(view, false, false); // Same calculation as getMeasurementIncludingMargin() - int measuredWidth = leftMargin + pWidth + rightMargin; - int measuredHeight = topMargin + pHeight + bottomMargin; + int mWidth = leftMargin + pWidth + rightMargin; + int mHeight = topMargin + pHeight + bottomMargin; // Alignment offsets: the location of the view relative to its alignment group. - int a2vx = colBounds.before - hAlignment.getAlignmentValue(view, measuredWidth); - int a2vy = rowBounds.before - vAlignment.getAlignmentValue(view, measuredHeight); + int a2vx = colBounds.before - hAlign.getAlignmentValue(view, mWidth, type); + int a2vy = rowBounds.before - vAlign.getAlignmentValue(view, mHeight, type); dx = c2ax + a2vx + leftMargin; dy = c2ay + a2vy + topMargin; @@ -877,15 +878,15 @@ public class GridLayout extends ViewGroup { cellHeight -= topMargin + bottomMargin; } else { // Alignment offsets: the location of the view relative to its alignment group. - int a2vx = colBounds.before - hAlignment.getAlignmentValue(view, pWidth); - int a2vy = rowBounds.before - vAlignment.getAlignmentValue(view, pHeight); + int a2vx = colBounds.before - hAlign.getAlignmentValue(view, pWidth, type); + int a2vy = rowBounds.before - vAlign.getAlignmentValue(view, pHeight, type); dx = c2ax + a2vx; dy = c2ay + a2vy; } - int width = hAlignment.getSizeInCell(view, pWidth, cellWidth); - int height = vAlignment.getSizeInCell(view, pHeight, cellHeight); + int width = hAlign.getSizeInCell(view, pWidth, cellWidth, type); + int height = vAlign.getSizeInCell(view, pHeight, cellHeight, type); int cx = paddingLeft + x1 + dx; int cy = paddingTop + y1 + dy; @@ -1003,7 +1004,7 @@ public class GridLayout extends ViewGroup { int size = getMeasurementIncludingMargin(c, horizontal, PRF); // todo test this works correctly when the returned value is UNDEFINED - int before = g.alignment.getAlignmentValue(c, size); + int before = g.alignment.getAlignmentValue(c, size, PRF); bounds.include(before, size - before); } } @@ -1459,6 +1460,7 @@ public class GridLayout extends ViewGroup { spanSizes = null; leadingMargins = null; trailingMargins = null; + arcs = null; minima = null; weights = null; locations = null; @@ -2156,57 +2158,59 @@ public class GridLayout extends ViewGroup { * {@link Group#alignment alignment}. Overall placement of the view in the cell * group is specified by the two alignments which act along each axis independently. * <p> - * An Alignment implementation must define the {@link #getAlignmentValue(View, int)} + * An Alignment implementation must define {@link #getAlignmentValue(View, int, int)}, * to return the appropriate value for the type of alignment being defined. * The enclosing algorithms position the children - * so that the values returned from the alignment + * so that the locations defined by the alignmnet values * are the same for all of the views in a group. * <p> * The GridLayout class defines the most common alignments used in general layout: * {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, {@link #RIGHT}, {@link #CENTER}, {@link * #BASELINE} and {@link #FILL}. */ - public static interface Alignment { + public static abstract class Alignment { /** * Returns an alignment value. In the case of vertical alignments the value * returned should indicate the distance from the top of the view to the * alignment location. * For horizontal alignments measurement is made from the left edge of the component. * - * @param view the view to which this alignment should be applied - * @param viewSize the measured size of the view - * @return the alignment value + * @param view the view to which this alignment should be applied + * @param viewSize the measured size of the view + * @param measurementType the type of measurement that should be made + * + * @return the alignment value */ - public int getAlignmentValue(View view, int viewSize); + public abstract int getAlignmentValue(View view, int viewSize, int measurementType); /** * Returns the size of the view specified by this alignment. * In the case of vertical alignments this method should return a height; for * horizontal alignments this method should return the width. + * <p> + * The default implementation returns {@code viewSize}. + * + * @param view the view to which this alignment should be applied + * @param viewSize the measured size of the view + * @param cellSize the size of the cell into which this view will be placed + * @param measurementType the type of measurement that should be made * - * @param view the view to which this alignment should be applied - * @param viewSize the measured size of the view - * @param cellSize the size of the cell into which this view will be placed - * @return the aligned size + * @return the aligned size */ - public int getSizeInCell(View view, int viewSize, int cellSize); - } - - private static abstract class AbstractAlignment implements Alignment { - public int getSizeInCell(View view, int viewSize, int cellSize) { + public int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) { return viewSize; } } - private static final Alignment LEADING = new AbstractAlignment() { - public int getAlignmentValue(View view, int viewSize) { + private static final Alignment LEADING = new Alignment() { + public int getAlignmentValue(View view, int viewSize, int measurementType) { return 0; } }; - private static final Alignment TRAILING = new AbstractAlignment() { - public int getAlignmentValue(View view, int viewSize) { + private static final Alignment TRAILING = new Alignment() { + public int getAlignmentValue(View view, int viewSize, int measurementType) { return viewSize; } }; @@ -2240,8 +2244,8 @@ public class GridLayout extends ViewGroup { * This constant may be used in both {@link LayoutParams#rowGroup rowGroups} and {@link * LayoutParams#columnGroup columnGroups}. */ - public static final Alignment CENTER = new AbstractAlignment() { - public int getAlignmentValue(View view, int viewSize) { + public static final Alignment CENTER = new Alignment() { + public int getAlignmentValue(View view, int viewSize, int measurementType) { return viewSize >> 1; } }; @@ -2253,8 +2257,8 @@ public class GridLayout extends ViewGroup { * * @see View#getBaseline() */ - public static final Alignment BASELINE = new AbstractAlignment() { - public int getAlignmentValue(View view, int height) { + public static final Alignment BASELINE = new Alignment() { + public int getAlignmentValue(View view, int viewSize, int measurementType) { if (view == null) { return UNDEFINED; } @@ -2274,11 +2278,12 @@ public class GridLayout extends ViewGroup { * {@link LayoutParams#columnGroup columnGroups}. */ public static final Alignment FILL = new Alignment() { - public int getAlignmentValue(View view, int viewSize) { + public int getAlignmentValue(View view, int viewSize, int measurementType) { return UNDEFINED; } - public int getSizeInCell(View view, int viewSize, int cellSize) { + @Override + public int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) { return cellSize; } }; diff --git a/core/java/com/android/internal/net/VpnConfig.aidl b/core/java/com/android/internal/net/VpnConfig.aidl new file mode 100644 index 0000000..be1684c --- /dev/null +++ b/core/java/com/android/internal/net/VpnConfig.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.net; + +parcelable VpnConfig; diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java new file mode 100644 index 0000000..18d9ec4 --- /dev/null +++ b/core/java/com/android/internal/net/VpnConfig.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.net; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A simple container used to carry information in VpnBuilder, VpnDialogs, + * and com.android.server.connectivity.Vpn. Internal use only. + * + * @hide + */ +public class VpnConfig implements Parcelable { + + public String packageName; + public String sessionName; + public String interfaceName; + public String configureActivity; + public int mtu = -1; + public String addresses; + public String routes; + public String dnsServers; + public long startTime = -1; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(packageName); + out.writeString(sessionName); + out.writeString(interfaceName); + out.writeString(configureActivity); + out.writeInt(mtu); + out.writeString(addresses); + out.writeString(routes); + out.writeString(dnsServers); + out.writeLong(startTime); + } + + public static final Parcelable.Creator<VpnConfig> CREATOR = + new Parcelable.Creator<VpnConfig>() { + @Override + public VpnConfig createFromParcel(Parcel in) { + VpnConfig config = new VpnConfig(); + config.packageName = in.readString(); + config.sessionName = in.readString(); + config.interfaceName = in.readString(); + config.configureActivity = in.readString(); + config.mtu = in.readInt(); + config.addresses = in.readString(); + config.routes = in.readString(); + config.dnsServers = in.readString(); + config.startTime = in.readLong(); + return config; + } + + @Override + public VpnConfig[] newArray(int size) { + return new VpnConfig[size]; + } + }; +} diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 84ad012..e301e44 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -796,7 +796,7 @@ static JNINativeMethod gMethods[] = { { "nCreateLayer", "(IIZ[I)I", (void*) android_view_GLES20Canvas_createLayer }, { "nResizeLayer", "(III[I)V" , (void*) android_view_GLES20Canvas_resizeLayer }, { "nCreateTextureLayer", "([I)I", (void*) android_view_GLES20Canvas_createTextureLayer }, - { "nUpdateTextureLayer", "(IIILjava/lang/String;)V", + { "nUpdateTextureLayer", "(IIILandroid/graphics/SurfaceTexture;)V", (void*) android_view_GLES20Canvas_updateTextureLayer }, { "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer }, { "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred }, diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp index c5d86c8..b046b23 100644 --- a/core/jni/android_view_TextureView.cpp +++ b/core/jni/android_view_TextureView.cpp @@ -17,6 +17,7 @@ #include "jni.h" #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_graphics_SurfaceTexture.h> #include <gui/SurfaceTexture.h> @@ -27,10 +28,10 @@ namespace android { // ---------------------------------------------------------------------------- static void android_view_TextureView_setDefaultBufferSize(JNIEnv* env, jobject, - jint surfaceTexture, jint width, jint height) { + jobject surface, jint width, jint height) { - sp<SurfaceTexture> surface = reinterpret_cast<SurfaceTexture*>(surfaceTexture); - surface->setDefaultBufferSize(width, height); + sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface)); + surfaceTexture->setDefaultBufferSize(width, height); } // ---------------------------------------------------------------------------- @@ -40,7 +41,8 @@ static void android_view_TextureView_setDefaultBufferSize(JNIEnv* env, jobject, const char* const kClassPathName = "android/view/TextureView"; static JNINativeMethod gMethods[] = { - { "nSetDefaultBufferSize", "(III)V", (void*) android_view_TextureView_setDefaultBufferSize } + { "nSetDefaultBufferSize", "(Landroid/graphics/SurfaceTexture;II)V", + (void*) android_view_TextureView_setDefaultBufferSize } }; int register_android_view_TextureView(JNIEnv* env) { diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp index 7a0668e..02974f9 100644 --- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp @@ -541,7 +541,7 @@ static JNINativeMethod methods[] = { {"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)I", (void*)jni_eglCreatePbufferSurface }, {"_eglCreatePixmapSurface", "(" SURFACE DISPLAY CONFIG OBJECT "[I)V", (void*)jni_eglCreatePixmapSurface }, {"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurface }, -{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG "I[I)I", (void*)jni_eglCreateWindowSurfaceTexture }, +{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurfaceTexture }, {"eglDestroyContext", "(" DISPLAY CONTEXT ")Z", (void*)jni_eglDestroyContext }, {"eglDestroySurface", "(" DISPLAY SURFACE ")Z", (void*)jni_eglDestroySurface }, {"eglMakeCurrent", "(" DISPLAY SURFACE SURFACE CONTEXT")Z", (void*)jni_eglMakeCurrent }, diff --git a/core/res/res/layout/preference_widget_seekbar.xml b/core/res/res/layout/preference_widget_seekbar.xml new file mode 100644 index 0000000..e4cf86d --- /dev/null +++ b/core/res/res/layout/preference_widget_seekbar.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Layout for a Preference in a PreferenceActivity. The + Preference is able to place a specific widget for its particular + type in the "widget_frame" layout. --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeight" + android:gravity="center_vertical" + android:paddingRight="?android:attr/scrollbarSize"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center" + android:minWidth="@dimen/preference_icon_minWidth" + android:orientation="horizontal"> + <ImageView + android:id="@+android:id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:minWidth="48dp" + /> + </LinearLayout> + + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="16dip" + android:layout_marginRight="8dip" + android:layout_marginTop="6dip" + android:layout_marginBottom="6dip" + android:layout_weight="1"> + + <TextView android:id="@+android:id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:ellipsize="marquee" + android:fadingEdge="horizontal" /> + + <TextView android:id="@+android:id/summary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@android:id/title" + android:layout_alignLeft="@android:id/title" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorSecondary" + android:maxLines="4" /> + + <!-- Preference should place its actual preference widget here. --> + <LinearLayout android:id="@+android:id/widget_frame" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_below="@android:id/summary" + android:layout_alignLeft="@android:id/title" + android:minWidth="@dimen/preference_widget_width" + android:gravity="center" + android:orientation="vertical" /> + + <SeekBar android:id="@+android:id/seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@android:id/summary" + android:layout_toRightOf="@android:id/widget_frame" + android:layout_alignParentRight="true" /> + + </RelativeLayout> + +</LinearLayout> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 879892e..d7b7dd0 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1790,6 +1790,9 @@ <string name="lockscreen_missing_sim_instructions">Please insert a SIM card.</string> <!-- Shown in the lock screen to ask the user to insert a SIM card when sim is missing or not readable. --> <string name="lockscreen_missing_sim_instructions_long">The SIM card is missing or not readable. Please insert a SIM card.</string> + <!-- Shown in the lock screen to inform the user to SIM card is permanently disabled. --> + <string name="lockscreen_permanent_disabled_sim_instructions">Your SIM card is permanently disabled.\n + Please contact your wireless service provider to obtain another SIM card.</string> <!-- Shown in the lock screen when there is emergency calls only mode. --> <string name="emergency_calls_only" msgid="2485604591272668370">Emergency calls only</string> diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java deleted file mode 100644 index 54a5e4e..0000000 --- a/core/tests/coretests/src/android/content/res/ConfigurationTest.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.res; - -import java.util.Locale; - -import android.test.AndroidTestCase; -import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetNew; - -public class ConfigurationTest extends AndroidTestCase { - - @TestTargetNew( - level = TestLevel.COMPLETE, - method = "getLayoutDirectionFromLocale", - args = {Locale.class} - ) - public void testGetLayoutDirectionFromLocale() { - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(null)); - - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.ENGLISH)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.CANADA)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.CANADA_FRENCH)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.FRANCE)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.FRENCH)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.GERMAN)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.GERMANY)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.ITALIAN)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.ITALY)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.UK)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.US)); - - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.ROOT)); - - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.CHINA)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.CHINESE)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.JAPAN)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.JAPANESE)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.KOREA)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.KOREAN)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.PRC)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.SIMPLIFIED_CHINESE)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.TAIWAN)); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(Locale.TRADITIONAL_CHINESE)); - - Locale locale = new Locale("ar"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "AE"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "BH"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "DZ"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "EG"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "IQ"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "JO"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "KW"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "LB"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "LY"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "MA"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "OM"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "QA"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "SA"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "SD"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "SY"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "TN"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ar", "YE"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - - locale = new Locale("fa"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("fa", "AF"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("fa", "IR"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - - locale = new Locale("iw"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("iw", "IL"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("he"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("he", "IL"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - - // The following test will not pass until we are able to take care about the scrip subtag - // thru having the "likelySubTags" file into ICU4C -// locale = new Locale("pa_Arab"); -// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, -// Configuration.getLayoutDirectionFromLocale(locale)); -// locale = new Locale("pa_Arab", "PK"); -// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, -// Configuration.getLayoutDirectionFromLocale(locale)); - - locale = new Locale("ps"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - locale = new Locale("ps", "AF"); - assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, - Configuration.getLayoutDirectionFromLocale(locale)); - - // The following test will not work as the localized display name would be "Urdu" with ICU 4.4 - // We will need ICU 4.6 to get the correct localized display name -// locale = new Locale("ur"); -// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, -// Configuration.getLayoutDirectionFromLocale(locale)); -// locale = new Locale("ur", "IN"); -// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, -// Configuration.getLayoutDirectionFromLocale(locale)); -// locale = new Locale("ur", "PK"); -// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, -// Configuration.getLayoutDirectionFromLocale(locale)); - - // The following test will not pass until we are able to take care about the scrip subtag - // thru having the "likelySubTags" file into ICU4C -// locale = new Locale("uz_Arab"); -// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, -// Configuration.getLayoutDirectionFromLocale(locale)); -// locale = new Locale("uz_Arab", "AF"); -// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, -// Configuration.getLayoutDirectionFromLocale(locale)); - } -} diff --git a/core/tests/coretests/src/android/util/LocaleUtilTest.java b/core/tests/coretests/src/android/util/LocaleUtilTest.java new file mode 100644 index 0000000..203781f --- /dev/null +++ b/core/tests/coretests/src/android/util/LocaleUtilTest.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 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. + */ + +package android.util; + +import java.util.Locale; + +import android.test.AndroidTestCase; +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetNew; + +import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE; +import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE; + +public class LocaleUtilTest extends AndroidTestCase { + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "getLayoutDirectionFromLocale", + args = {Locale.class} + ) + public void testGetLayoutDirectionFromLocale() { + assertEquals(TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(null)); + + assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.ENGLISH)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.CANADA)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.CANADA_FRENCH)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.FRANCE)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.FRENCH)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.GERMAN)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.GERMANY)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.ITALIAN)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.ITALY)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.UK)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.US)); + + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.ROOT)); + + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.CHINA)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.CHINESE)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.JAPAN)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.JAPANESE)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.KOREA)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.KOREAN)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.PRC)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.SIMPLIFIED_CHINESE)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.TAIWAN)); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(Locale.TRADITIONAL_CHINESE)); + + Locale locale = new Locale("ar"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "AE"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "BH"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "DZ"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "EG"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "IQ"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "JO"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "KW"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "LB"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "LY"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "MA"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "OM"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "QA"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "SA"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "SD"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "SY"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "TN"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ar", "YE"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + + locale = new Locale("fa"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("fa", "AF"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("fa", "IR"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + + locale = new Locale("iw"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("iw", "IL"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("he"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("he", "IL"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + + locale = new Locale("pa_Arab"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("pa_Arab", "PK"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + + locale = new Locale("ps"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ps", "AF"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + + locale = new Locale("ur"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ur", "IN"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("ur", "PK"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + + locale = new Locale("uz_Arab"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + locale = new Locale("uz_Arab", "AF"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + + // Locale without a real language + locale = new Locale("zz"); + assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE, + LocaleUtil.getLayoutDirectionFromLocale(locale)); + } +} diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp index c37b4f8..458f1b6 100644 --- a/drm/common/IDrmManagerService.cpp +++ b/drm/common/IDrmManagerService.cpp @@ -37,7 +37,7 @@ using namespace android; -static void writeDecrptHandleToParcelData( +static void writeDecryptHandleToParcelData( const DecryptHandle* handle, Parcel* data) { data->writeInt32(handle->decryptId); data->writeString8(handle->mimeType); @@ -46,14 +46,14 @@ static void writeDecrptHandleToParcelData( int size = handle->copyControlVector.size(); data->writeInt32(size); - for(int i = 0; i < size; i++) { + for (int i = 0; i < size; i++) { data->writeInt32(handle->copyControlVector.keyAt(i)); data->writeInt32(handle->copyControlVector.valueAt(i)); } size = handle->extendedData.size(); data->writeInt32(size); - for(int i = 0; i < size; i++) { + for (int i = 0; i < size; i++) { data->writeString8(handle->extendedData.keyAt(i)); data->writeString8(handle->extendedData.valueAt(i)); } @@ -77,14 +77,14 @@ static void readDecryptHandleFromParcelData( handle->status = data.readInt32(); int size = data.readInt32(); - for (int i = 0; i < size; i ++) { + for (int i = 0; i < size; i++) { DrmCopyControl key = (DrmCopyControl)data.readInt32(); int value = data.readInt32(); handle->copyControlVector.add(key, value); } size = data.readInt32(); - for (int i = 0; i < size; i ++) { + for (int i = 0; i < size; i++) { String8 key = data.readString8(); String8 value = data.readString8(); handle->extendedData.add(key, value); @@ -416,7 +416,7 @@ status_t BpDrmManagerService::consumeRights( data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); - writeDecrptHandleToParcelData(decryptHandle, &data); + writeDecryptHandleToParcelData(decryptHandle, &data); data.writeInt32(action); data.writeInt32(static_cast< int>(reserve)); @@ -433,7 +433,7 @@ status_t BpDrmManagerService::setPlaybackStatus( data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); - writeDecrptHandleToParcelData(decryptHandle, &data); + writeDecryptHandleToParcelData(decryptHandle, &data); data.writeInt32(playbackStatus); data.writeInt64(position); @@ -646,7 +646,7 @@ status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* d data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); - writeDecrptHandleToParcelData(decryptHandle, &data); + writeDecryptHandleToParcelData(decryptHandle, &data); remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply); @@ -662,7 +662,7 @@ status_t BpDrmManagerService::initializeDecryptUnit( data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); - writeDecrptHandleToParcelData(decryptHandle, &data); + writeDecryptHandleToParcelData(decryptHandle, &data); data.writeInt32(decryptUnitId); @@ -682,7 +682,7 @@ status_t BpDrmManagerService::decrypt( data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); - writeDecrptHandleToParcelData(decryptHandle, &data); + writeDecryptHandleToParcelData(decryptHandle, &data); data.writeInt32(decryptUnitId); data.writeInt32((*decBuffer)->length); @@ -715,7 +715,7 @@ status_t BpDrmManagerService::finalizeDecryptUnit( data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); - writeDecrptHandleToParcelData(decryptHandle, &data); + writeDecryptHandleToParcelData(decryptHandle, &data); data.writeInt32(decryptUnitId); @@ -733,7 +733,7 @@ ssize_t BpDrmManagerService::pread( data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor()); data.writeInt32(uniqueId); - writeDecrptHandleToParcelData(decryptHandle, &data); + writeDecryptHandleToParcelData(decryptHandle, &data); data.writeInt32(numBytes); data.writeInt64(offset); @@ -1244,7 +1244,7 @@ status_t BnDrmManagerService::onTransact( = openDecryptSession(uniqueId, fd, data.readInt64(), data.readInt64()); if (NULL != handle) { - writeDecrptHandleToParcelData(handle, reply); + writeDecryptHandleToParcelData(handle, reply); clearDecryptHandle(handle); delete handle; handle = NULL; } @@ -1262,7 +1262,7 @@ status_t BnDrmManagerService::onTransact( DecryptHandle* handle = openDecryptSession(uniqueId, uri.string()); if (NULL != handle) { - writeDecrptHandleToParcelData(handle, reply); + writeDecryptHandleToParcelData(handle, reply); clearDecryptHandle(handle); delete handle; handle = NULL; diff --git a/drm/java/android/drm/DrmInfoRequest.java b/drm/java/android/drm/DrmInfoRequest.java index 2222ae8..1429fa5 100755 --- a/drm/java/android/drm/DrmInfoRequest.java +++ b/drm/java/android/drm/DrmInfoRequest.java @@ -32,16 +32,16 @@ public class DrmInfoRequest { */ public static final int TYPE_REGISTRATION_INFO = 1; /** - * Acquires information for unregistering the DRM server. - */ + * Acquires information for unregistering the DRM server. + */ public static final int TYPE_UNREGISTRATION_INFO = 2; /** - * Acquires rights information. - */ + * Acquires rights information. + */ public static final int TYPE_RIGHTS_ACQUISITION_INFO = 3; /** - * Acquires the progress of the rights acquisition. - */ + * Acquires the progress of the rights acquisition. + */ public static final int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4; /** diff --git a/drm/java/android/drm/DrmInfoStatus.java b/drm/java/android/drm/DrmInfoStatus.java index b04694b..5c12ae3 100755 --- a/drm/java/android/drm/DrmInfoStatus.java +++ b/drm/java/android/drm/DrmInfoStatus.java @@ -31,20 +31,20 @@ public class DrmInfoStatus { public static final int STATUS_ERROR = 2; /** - * The status of the communication. - */ + * The status of the communication. + */ public final int statusCode; /** - * The type of DRM information processed. - */ + * The type of DRM information processed. + */ public final int infoType; /** - * The MIME type of the content. - */ + * The MIME type of the content. + */ public final String mimeType; /** - * The processed data. - */ + * The processed data. + */ public final ProcessedData data; /** diff --git a/drm/libdrmframework/include/PlugInManager.h b/drm/libdrmframework/include/PlugInManager.h index 8029138..7bb143f 100644 --- a/drm/libdrmframework/include/PlugInManager.h +++ b/drm/libdrmframework/include/PlugInManager.h @@ -202,7 +202,7 @@ private: Vector<String8> getPlugInPathList(const String8& rsDirPath) { Vector<String8> fileList; DIR* pDir = opendir(rsDirPath.string()); - struct dirent* pEntry = new dirent(); + struct dirent* pEntry; while (NULL != pDir && NULL != (pEntry = readdir(pDir))) { if (!isPlugIn(pEntry)) { @@ -219,8 +219,6 @@ private: if (NULL != pDir) { closedir(pDir); } - delete pEntry; - pEntry = NULL; return fileList; } diff --git a/include/utils/BlobCache.h b/include/utils/BlobCache.h index 8f76d72..dc45ff0 100644 --- a/include/utils/BlobCache.h +++ b/include/utils/BlobCache.h @@ -82,6 +82,9 @@ private: BlobCache(const BlobCache&); void operator=(const BlobCache&); + // A random function helper to get around MinGW not having nrand48() + long int blob_random(); + // clean evicts a randomly chosen set of entries from the cache such that // the total size of all remaining entries is less than mMaxTotalSize/2. void clean(); diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk index 9fabf8d..d9cc6b6 100644 --- a/libs/rs/Android.mk +++ b/libs/rs/Android.mk @@ -119,6 +119,7 @@ LOCAL_SRC_FILES:= \ driver/rsdBcc.cpp \ driver/rsdCore.cpp \ driver/rsdFrameBuffer.cpp \ + driver/rsdFrameBufferObj.cpp \ driver/rsdGL.cpp \ driver/rsdMesh.cpp \ driver/rsdMeshObj.cpp \ diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp index 8bfc185..01a0cf6 100644 --- a/libs/rs/driver/rsdAllocation.cpp +++ b/libs/rs/driver/rsdAllocation.cpp @@ -19,6 +19,7 @@ #include "rsdBcc.h" #include "rsdRuntime.h" #include "rsdAllocation.h" +#include "rsdFrameBufferObj.h" #include "rsAllocation.h" @@ -244,6 +245,9 @@ bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) { drv->uploadDeferred = true; } + + drv->readBackFBO = NULL; + return true; } @@ -269,6 +273,10 @@ void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) { free(drv->mallocPtr); drv->mallocPtr = NULL; } + if (drv->readBackFBO != NULL) { + delete drv->readBackFBO; + drv->readBackFBO = NULL; + } free(drv); alloc->mHal.drv = NULL; } @@ -292,13 +300,52 @@ void rsdAllocationResize(const Context *rsc, const Allocation *alloc, } } +static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) { + if (!alloc->getIsScript()) { + return; // nothing to sync + } + + RsdHal *dc = (RsdHal *)rsc->mHal.drv; + RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer; + + DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; + if (!drv->textureID && !drv->renderTargetID) { + return; // nothing was rendered here yet, so nothing to sync + } + if (drv->readBackFBO == NULL) { + drv->readBackFBO = new RsdFrameBufferObj(); + drv->readBackFBO->setColorTarget(drv, 0); + drv->readBackFBO->setDimensions(alloc->getType()->getDimX(), + alloc->getType()->getDimY()); + } + + // Bind the framebuffer object so we can read back from it + drv->readBackFBO->setActive(rsc); + + // Do the readback + glReadPixels(0, 0, alloc->getType()->getDimX(), alloc->getType()->getDimY(), + drv->glFormat, drv->glType, alloc->getPtr()); + + // Revert framebuffer to its original + lastFbo->setActive(rsc); +} void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc, RsAllocationUsageType src) { DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; - if (!drv->uploadDeferred) { + if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { + if(!alloc->getIsRenderTarget()) { + rsc->setError(RS_ERROR_FATAL_DRIVER, + "Attempting to sync allocation from render target, " + "for non-render target allocation"); + } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) { + rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA" + "render target"); + } else { + rsdAllocationSyncFromFBO(rsc, alloc); + } return; } @@ -382,7 +429,40 @@ void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc, const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff, uint32_t dstLod, uint32_t count, const android::renderscript::Allocation *srcAlloc, - uint32_t srcXoff, uint32_t srcLod){ + uint32_t srcXoff, uint32_t srcLod) { +} + +uint8_t *getOffsetPtr(const android::renderscript::Allocation *alloc, + uint32_t xoff, uint32_t yoff, uint32_t lod, + RsAllocationCubemapFace face) { + uint8_t *ptr = static_cast<uint8_t *>(alloc->getPtr()); + ptr += alloc->getType()->getLODOffset(lod, xoff, yoff); + + if (face != 0) { + uint32_t totalSizeBytes = alloc->getType()->getSizeBytes(); + uint32_t faceOffset = totalSizeBytes / 6; + ptr += faceOffset * (uint32_t)face; + } + return ptr; +} + + +void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc, + const android::renderscript::Allocation *dstAlloc, + uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod, + RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h, + const android::renderscript::Allocation *srcAlloc, + uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, + RsAllocationCubemapFace srcFace) { + uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes(); + for (uint32_t i = 0; i < h; i ++) { + uint8_t *dstPtr = getOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace); + uint8_t *srcPtr = getOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace); + memcpy(dstPtr, srcPtr, w * elementSize); + + LOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)", + dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace); + } } void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, @@ -392,6 +472,14 @@ void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc, const android::renderscript::Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) { + if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) { + rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not " + "yet implemented."); + return; + } + rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, + dstLod, dstFace, w, h, srcAlloc, + srcXoff, srcYoff, srcLod, srcFace); } void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc, diff --git a/libs/rs/driver/rsdAllocation.h b/libs/rs/driver/rsdAllocation.h index 7555c4a..4fc4419 100644 --- a/libs/rs/driver/rsdAllocation.h +++ b/libs/rs/driver/rsdAllocation.h @@ -23,6 +23,8 @@ #include <GLES/gl.h> #include <GLES2/gl2.h> +class RsdFrameBufferObj; + struct DrvAllocation { // Is this a legal structure to be used as a texture source. // Initially this will require 1D or 2D and color data @@ -42,8 +44,9 @@ struct DrvAllocation { GLenum glType; GLenum glFormat; - bool uploadDeferred; + + RsdFrameBufferObj * readBackFBO; }; GLenum rsdTypeToGLType(RsDataType t); diff --git a/libs/rs/driver/rsdFrameBuffer.cpp b/libs/rs/driver/rsdFrameBuffer.cpp index ce72b5d..8c1b12d 100644 --- a/libs/rs/driver/rsdFrameBuffer.cpp +++ b/libs/rs/driver/rsdFrameBuffer.cpp @@ -17,6 +17,7 @@ #include "rsdCore.h" #include "rsdFrameBuffer.h" +#include "rsdFrameBufferObj.h" #include "rsdAllocation.h" #include "rsContext.h" @@ -28,133 +29,70 @@ using namespace android; using namespace android::renderscript; -struct DrvFrameBuffer { - GLuint mFBOId; -}; - -void checkError(const Context *rsc) { - GLenum status; - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - switch (status) { - case GL_FRAMEBUFFER_COMPLETE: - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - rsc->setError(RS_ERROR_BAD_VALUE, - "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - rsc->setError(RS_ERROR_BAD_VALUE, - "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - rsc->setError(RS_ERROR_BAD_VALUE, - "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - rsc->setError(RS_ERROR_BAD_VALUE, - "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED"); - break; - } -} - - void setDepthAttachment(const Context *rsc, const FBOCache *fb) { + RsdFrameBufferObj *fbo = (RsdFrameBufferObj*)fb->mHal.drv; + + DrvAllocation *depth = NULL; if (fb->mHal.state.depthTarget.get() != NULL) { - DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.depthTarget->mHal.drv; - - if (drv->textureID) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, drv->textureID, 0); - } else { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, drv->renderTargetID); + depth = (DrvAllocation *)fb->mHal.state.depthTarget->mHal.drv; + + if (depth->uploadDeferred) { + rsdAllocationSyncAll(rsc, fb->mHal.state.depthTarget.get(), + RS_ALLOCATION_USAGE_SCRIPT); } - } else { - // Reset last attachment - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); } + fbo->setDepthTarget(depth); } void setColorAttachment(const Context *rsc, const FBOCache *fb) { + RsdFrameBufferObj *fbo = (RsdFrameBufferObj*)fb->mHal.drv; // Now attach color targets for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) { - uint32_t texID = 0; + DrvAllocation *color = NULL; if (fb->mHal.state.colorTargets[i].get() != NULL) { - DrvAllocation *drv = (DrvAllocation *)fb->mHal.state.colorTargets[i]->mHal.drv; - - if (drv->textureID) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, - GL_TEXTURE_2D, drv->textureID, 0); - } else { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, - GL_RENDERBUFFER, drv->renderTargetID); - } - } else { - // Reset last attachment - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, - GL_RENDERBUFFER, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, - GL_TEXTURE_2D, 0, 0); - } - } -} - -bool renderToFramebuffer(const FBOCache *fb) { - if (fb->mHal.state.depthTarget.get() != NULL) { - return false; - } + color = (DrvAllocation *)fb->mHal.state.colorTargets[i]->mHal.drv; - for (uint32_t i = 0; i < fb->mHal.state.colorTargetsCount; i ++) { - if (fb->mHal.state.colorTargets[i].get() != NULL) { - return false; + if (color->uploadDeferred) { + rsdAllocationSyncAll(rsc, fb->mHal.state.colorTargets[i].get(), + RS_ALLOCATION_USAGE_SCRIPT); + } } + fbo->setColorTarget(color, i); } - return true; } - bool rsdFrameBufferInit(const Context *rsc, const FBOCache *fb) { - DrvFrameBuffer *drv = (DrvFrameBuffer *)calloc(1, sizeof(DrvFrameBuffer)); - if (drv == NULL) { + RsdFrameBufferObj *fbo = new RsdFrameBufferObj(); + if (fbo == NULL) { return false; } - fb->mHal.drv = drv; - drv->mFBOId = 0; + fb->mHal.drv = fbo; + + RsdHal *dc = (RsdHal *)rsc->mHal.drv; + dc->gl.currentFrameBuffer = fbo; return true; } void rsdFrameBufferSetActive(const Context *rsc, const FBOCache *fb) { - DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv; - - bool framebuffer = renderToFramebuffer(fb); - if (!framebuffer) { - if(drv->mFBOId == 0) { - glGenFramebuffers(1, &drv->mFBOId); - } - glBindFramebuffer(GL_FRAMEBUFFER, drv->mFBOId); - - setDepthAttachment(rsc, fb); - setColorAttachment(rsc, fb); - - glViewport(0, 0, fb->mHal.state.colorTargets[0]->getType()->getDimX(), - fb->mHal.state.colorTargets[0]->getType()->getDimY()); - - checkError(rsc); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, rsc->getWidth(), rsc->getHeight()); + setDepthAttachment(rsc, fb); + setColorAttachment(rsc, fb); + + RsdFrameBufferObj *fbo = (RsdFrameBufferObj *)fb->mHal.drv; + if (fb->mHal.state.colorTargets[0].get()) { + fbo->setDimensions(fb->mHal.state.colorTargets[0]->getType()->getDimX(), + fb->mHal.state.colorTargets[0]->getType()->getDimY()); + } else if (fb->mHal.state.depthTarget.get()) { + fbo->setDimensions(fb->mHal.state.depthTarget->getType()->getDimX(), + fb->mHal.state.depthTarget->getType()->getDimY()); } + + fbo->setActive(rsc); } void rsdFrameBufferDestroy(const Context *rsc, const FBOCache *fb) { - DrvFrameBuffer *drv = (DrvFrameBuffer *)fb->mHal.drv; - if(drv->mFBOId != 0) { - glDeleteFramebuffers(1, &drv->mFBOId); - } - - free(fb->mHal.drv); + RsdFrameBufferObj *fbo = (RsdFrameBufferObj *)fb->mHal.drv; + delete fbo; fb->mHal.drv = NULL; } diff --git a/libs/rs/driver/rsdFrameBufferObj.cpp b/libs/rs/driver/rsdFrameBufferObj.cpp new file mode 100644 index 0000000..145bf34 --- /dev/null +++ b/libs/rs/driver/rsdFrameBufferObj.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "rsdFrameBufferObj.h" +#include "rsdAllocation.h" + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +using namespace android; +using namespace android::renderscript; + +RsdFrameBufferObj::RsdFrameBufferObj() { + mFBOId = 0; + mWidth = 0; + mHeight = 0; + mColorTargetsCount = 1; + mColorTargets = new DrvAllocation*[mColorTargetsCount]; + for (uint32_t i = 0; i < mColorTargetsCount; i ++) { + mColorTargets[i] = 0; + } + mDepthTarget = NULL; + mDirty = true; +} + +RsdFrameBufferObj::~RsdFrameBufferObj() { + if(mFBOId != 0) { + glDeleteFramebuffers(1, &mFBOId); + } + delete [] mColorTargets; +} + +void RsdFrameBufferObj::checkError(const Context *rsc) { + GLenum status; + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + switch (status) { + case GL_FRAMEBUFFER_COMPLETE: + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + rsc->setError(RS_ERROR_BAD_VALUE, + "Unable to set up render Target: RFRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + rsc->setError(RS_ERROR_BAD_VALUE, + "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + rsc->setError(RS_ERROR_BAD_VALUE, + "Unable to set up render Target: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + rsc->setError(RS_ERROR_BAD_VALUE, + "Unable to set up render Target: GL_FRAMEBUFFER_UNSUPPORTED"); + break; + } +} + + +void RsdFrameBufferObj::setDepthAttachment() { + if (mDepthTarget != NULL) { + if (mDepthTarget->textureID) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, mDepthTarget->textureID, 0); + } else { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, mDepthTarget->renderTargetID); + } + } else { + // Reset last attachment + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + } +} + +void RsdFrameBufferObj::setColorAttachment() { + // Now attach color targets + for (uint32_t i = 0; i < mColorTargetsCount; i ++) { + if (mColorTargets[i] != NULL) { + if (mColorTargets[i]->textureID) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, + GL_TEXTURE_2D, mColorTargets[i]->textureID, 0); + } else { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, + GL_RENDERBUFFER, mColorTargets[i]->renderTargetID); + } + } else { + // Reset last attachment + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, + GL_RENDERBUFFER, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, + GL_TEXTURE_2D, 0, 0); + } + } +} + +bool RsdFrameBufferObj::renderToFramebuffer() { + if (mDepthTarget != NULL) { + return false; + } + + for (uint32_t i = 0; i < mColorTargetsCount; i ++) { + if (mColorTargets[i] != NULL) { + return false; + } + } + return true; +} + +void RsdFrameBufferObj::setActive(const Context *rsc) { + bool framebuffer = renderToFramebuffer(); + if (!framebuffer) { + if(mFBOId == 0) { + glGenFramebuffers(1, &mFBOId); + } + glBindFramebuffer(GL_FRAMEBUFFER, mFBOId); + + if (mDirty) { + setDepthAttachment(); + setColorAttachment(); + mDirty = false; + } + + glViewport(0, 0, mWidth, mHeight); + checkError(rsc); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, rsc->getWidth(), rsc->getHeight()); + } +} diff --git a/libs/rs/driver/rsdFrameBufferObj.h b/libs/rs/driver/rsdFrameBufferObj.h new file mode 100644 index 0000000..c6e7deb --- /dev/null +++ b/libs/rs/driver/rsdFrameBufferObj.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RSD_FRAMEBUFFER_OBJ_H_ +#define _RSD_FRAMEBUFFER_OBJ_H_ + +#include <rsContext.h> + +class DrvAllocation; + +class RsdFrameBufferObj { +public: + RsdFrameBufferObj(); + ~RsdFrameBufferObj(); + + void setActive(const android::renderscript::Context *rsc); + void setColorTarget(DrvAllocation *color, uint32_t index) { + mColorTargets[index] = color; + mDirty = true; + } + void setDepthTarget(DrvAllocation *depth) { + mDepthTarget = depth; + mDirty = true; + } + void setDimensions(uint32_t width, uint32_t height) { + mWidth = width; + mHeight = height; + } +protected: + uint32_t mFBOId; + DrvAllocation **mColorTargets; + uint32_t mColorTargetsCount; + DrvAllocation *mDepthTarget; + + uint32_t mWidth; + uint32_t mHeight; + + bool mDirty; + + bool renderToFramebuffer(); + void checkError(const android::renderscript::Context *rsc); + void setColorAttachment(); + void setDepthAttachment(); +}; + +#endif //_RSD_FRAMEBUFFER_STATE_H_ diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp index a70589b..3ff03b4 100644 --- a/libs/rs/driver/rsdGL.cpp +++ b/libs/rs/driver/rsdGL.cpp @@ -39,6 +39,7 @@ #include "rsContext.h" #include "rsdShaderCache.h" #include "rsdVertexArray.h" +#include "rsdFrameBufferObj.h" using namespace android; using namespace android::renderscript; @@ -294,6 +295,7 @@ bool rsdGLInit(const Context *rsc) { dc->gl.shaderCache = new RsdShaderCache(); dc->gl.vertexArrayState = new RsdVertexArrayState(); dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs); + dc->gl.currentFrameBuffer = NULL; LOGV("initGLThread end %p", rsc); return true; diff --git a/libs/rs/driver/rsdGL.h b/libs/rs/driver/rsdGL.h index 01c8438..0d5b7e7 100644 --- a/libs/rs/driver/rsdGL.h +++ b/libs/rs/driver/rsdGL.h @@ -22,6 +22,7 @@ class RsdShaderCache; class RsdVertexArrayState; +class RsdFrameBufferObj; typedef void (* InvokeFunc_t)(void); typedef void (*WorkerCallback_t)(void *usr, uint32_t idx); @@ -68,6 +69,7 @@ typedef struct RsdGLRec { uint32_t height; RsdShaderCache *shaderCache; RsdVertexArrayState *vertexArrayState; + RsdFrameBufferObj *currentFrameBuffer; } RsdGL; diff --git a/libs/rs/driver/rsdMeshObj.cpp b/libs/rs/driver/rsdMeshObj.cpp index c220ac1..4315c0d 100644 --- a/libs/rs/driver/rsdMeshObj.cpp +++ b/libs/rs/driver/rsdMeshObj.cpp @@ -138,7 +138,10 @@ void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, ui for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) { const Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[ct].get(); - rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT); + DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; + if (drv->uploadDeferred) { + rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT); + } } // update attributes with either buffer information or data ptr based on their current state @@ -163,7 +166,9 @@ void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, ui const Allocation *idxAlloc = prim->mIndexBuffer.get(); if (idxAlloc) { DrvAllocation *drvAlloc = (DrvAllocation *)idxAlloc->mHal.drv; - rsdAllocationSyncAll(rsc, idxAlloc, RS_ALLOCATION_USAGE_SCRIPT); + if (drvAlloc->uploadDeferred) { + rsdAllocationSyncAll(rsc, idxAlloc, RS_ALLOCATION_USAGE_SCRIPT); + } if (drvAlloc->bufferID) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drvAlloc->bufferID); diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp index bd8b3c3..25302aa 100644 --- a/libs/rs/driver/rsdRuntimeStubs.cpp +++ b/libs/rs/driver/rsdRuntimeStubs.cpp @@ -95,6 +95,8 @@ static void SC_AllocationCopy1DRange(Allocation *dstAlloc, Allocation *srcAlloc, uint32_t srcOff, uint32_t srcMip) { GET_TLS(); + rsrAllocationCopy1DRange(rsc, dstAlloc, dstOff, dstMip, count, + srcAlloc, srcOff, srcMip); } static void SC_AllocationCopy2DRange(Allocation *dstAlloc, @@ -105,6 +107,11 @@ static void SC_AllocationCopy2DRange(Allocation *dstAlloc, uint32_t srcXoff, uint32_t srcYoff, uint32_t srcMip, uint32_t srcFace) { GET_TLS(); + rsrAllocationCopy2DRange(rsc, dstAlloc, + dstXoff, dstYoff, dstMip, dstFace, + width, height, + srcAlloc, + srcXoff, srcYoff, srcMip, srcFace); } diff --git a/libs/rs/rsFBOCache.cpp b/libs/rs/rsFBOCache.cpp index 6960ef2..c5c64c2 100644 --- a/libs/rs/rsFBOCache.cpp +++ b/libs/rs/rsFBOCache.cpp @@ -80,16 +80,6 @@ void FBOCache::setup(Context *rsc) { return; } - if (mHal.state.depthTarget.get() != NULL) { - mHal.state.depthTarget->syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT); - } - - for (uint32_t i = 0; i < mHal.state.colorTargetsCount; i ++) { - if (mHal.state.colorTargets[i].get() != NULL) { - mHal.state.colorTargets[i]->syncAll(rsc, RS_ALLOCATION_USAGE_SCRIPT); - } - } - rsc->mHal.funcs.framebuffer.setActive(rsc, this); mDirty = false; diff --git a/libs/utils/BlobCache.cpp b/libs/utils/BlobCache.cpp index 1298fa7..590576a 100644 --- a/libs/utils/BlobCache.cpp +++ b/libs/utils/BlobCache.cpp @@ -31,9 +31,13 @@ BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize mMaxTotalSize(maxTotalSize), mTotalSize(0) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); +#ifdef _WIN32 + srand(now); +#else mRandState[0] = (now >> 0) & 0xFFFF; mRandState[1] = (now >> 16) & 0xFFFF; mRandState[2] = (now >> 32) & 0xFFFF; +#endif LOGV("initializing random seed using %lld", now); } @@ -148,11 +152,19 @@ size_t BlobCache::get(const void* key, size_t keySize, void* value, return valueBlobSize; } +long int BlobCache::blob_random() { +#ifdef _WIN32 + return rand(); +#else + return nrand48(mRandState); +#endif +} + void BlobCache::clean() { // Remove a random cache entry until the total cache size gets below half // the maximum total cache size. while (mTotalSize > mMaxTotalSize / 2) { - size_t i = size_t(nrand48(mRandState) % (mCacheEntries.size())); + size_t i = size_t(blob_random() % (mCacheEntries.size())); const CacheEntry& entry(mCacheEntries[i]); mTotalSize -= entry.getKey()->getSize() + entry.getValue()->getSize(); mCacheEntries.removeAt(i); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java index d6e1346..f3a91c5 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java @@ -1,57 +1,54 @@ /* * 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 + * 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 + * 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. + * 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.mediaframeworktest; /** - * - * This class has the names of the all the activity name and variables - * in the instrumentation test. + * + * This class has the names of the all the activity name and variables in the + * instrumentation test. * */ public class MediaNames { - //A directory to hold all kinds of media files + // A directory to hold all kinds of media files public static final String MEDIA_SAMPLE_POOL = "/sdcard/media_api/samples/"; - //Audio files - public static final String MP3CBR = "/sdcard/media_api/music/MP3_256kbps_2ch.mp3"; - public static final String MP3VBR = "/sdcard/media_api/music/MP3_256kbps_2ch_VBR.mp3"; + // Audio files + public static final String MP3CBR = "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3"; + public static final String MP3VBR = "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_VBR.mp3"; + public static final String MP3ABR = "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_ABR.mp3"; public static final String SHORTMP3 = "/sdcard/media_api/music/SHORTMP3.mp3"; public static final String MIDI = "/sdcard/media_api/music/ants.mid"; - public static final String WMA9 = "/sdcard/media_api/music/WMA9.wma"; - public static final String WMA10 = "/sdcard/media_api/music/WMA10.wma"; public static final String WAV = "/sdcard/media_api/music/rings_2ch.wav"; public static final String AMR = "/sdcard/media_api/music/test_amr_ietf.amr"; - public static final String OGG = "/sdcard/media_api/music/Revelation.ogg"; public static final String SINE_200_1000 = "/sdcard/media_api/music/sine_200+1000Hz_44K_mo.wav"; - + // public static final String OGG = + // "/sdcard/media_api/music/Revelation.ogg"; + public static final int MP3CBR_LENGTH = 71000; public static final int MP3VBR_LENGTH = 71000; public static final int SHORTMP3_LENGTH = 286; public static final int MIDI_LENGTH = 17000; - public static final int WMA9_LENGTH = 126559; - public static final int WMA10_LENGTH = 126559; public static final int AMR_LENGTH = 37000; - public static final int OGG_LENGTH = 4000; public static final int SEEK_TIME = 10000; - + public static final long PAUSE_WAIT_TIME = 3000; public static final long WAIT_TIME = 2000; public static final long WAIT_SNAPSHOT_TIME = 5000; - //local video + // local video public static final String VIDEO_MP4 = "/sdcard/media_api/video/MPEG4_320_AAC_64.mp4"; public static final String VIDEO_SHORT_3GP = "/sdcard/media_api/video/short.3gp"; public static final String VIDEO_LARGE_SIZE_3GP = "/sdcard/media_api/video/border_large.3gp"; @@ -59,185 +56,105 @@ public class MediaNames { public static final String VIDEO_H263_AMR = "/sdcard/media_api/video/H263_56_AMRNB_6.3gp"; public static final String VIDEO_H264_AAC = "/sdcard/media_api/video/H264_320_AAC_64.3gp"; public static final String VIDEO_H264_AMR = "/sdcard/media_api/video/H264_320_AMRNB_6.3gp"; - public static final String VIDEO_WMV = "/sdcard/media_api/video/bugs.wmv"; public static final String VIDEO_HIGHRES_H263 = "/sdcard/media_api/video/H263_500_AMRNB_12.3gp"; public static final String VIDEO_HIGHRES_MP4 = "/sdcard/media_api/video/H264_500_AAC_128.3gp"; - - //Media Recorder + public static final String VIDEO_WEBM = "/sdcard/media_api/video/big-buck-bunny_trailer.webm"; + + // Media Recorder public static final String RECORDER_OUTPUT = "/sdcard/media_api/recorderOutput.amr"; - //video thumbnail + // video thumbnail public static final String THUMBNAIL_OUTPUT = "/sdcard/media_api/videoThumbnail.png"; public static final String GOLDEN_THUMBNAIL_OUTPUT = "/sdcard/media_api/goldenThumbnail.png"; - public static final String GOLDEN_THUMBNAIL_OUTPUT_2 = "/sdcard/media_api/goldenThumbnail2.png"; - - //Metadata Utility - public static final String[] THUMBNAIL_CAPTURE_TEST_FILES = { - "/sdcard/media_api/metadata/test.mp4", - "/sdcard/media_api/metadata/test1.3gp", - "/sdcard/media_api/metadata/test2.3gp", - "/sdcard/media_api/metadata/test3.3gp", - "/sdcard/media_api/metadata/test4.3gp", - "/sdcard/media_api/metadata/test5.3gp", - "/sdcard/media_api/metadata/test6.3gp", - "/sdcard/media_api/metadata/test7.3gp", - "/sdcard/media_api/metadata/test8.3gp", - "/sdcard/media_api/metadata/test9.3gp", - "/sdcard/media_api/metadata/test10.3gp", - "/sdcard/media_api/metadata/test11.3gp", - "/sdcard/media_api/metadata/test12.3gp", - "/sdcard/media_api/metadata/test13.3gp", - "/sdcard/media_api/metadata/test14.3gp", - "/sdcard/media_api/metadata/test15.3gp", - "/sdcard/media_api/metadata/test16.3gp", - "/sdcard/media_api/metadata/test17.3gp", - "/sdcard/media_api/metadata/test18.3gp", - "/sdcard/media_api/metadata/test19.3gp", - "/sdcard/media_api/metadata/test20.3gp", - "/sdcard/media_api/metadata/test21.3gp", - "/sdcard/media_api/metadata/test22.3gp", - "/sdcard/media_api/metadata/test23.3gp", - "/sdcard/media_api/metadata/test24.3gp", - "/sdcard/media_api/metadata/test25.3gp", - "/sdcard/media_api/metadata/test26.3gp", - "/sdcard/media_api/metadata/test27.3gp", - "/sdcard/media_api/metadata/test28.3gp", - "/sdcard/media_api/metadata/test29.3gp", - "/sdcard/media_api/metadata/test30.3gp", - "/sdcard/media_api/metadata/test31.3gp", - "/sdcard/media_api/metadata/test32.3gp", - "/sdcard/media_api/metadata/test33.3gp", - "/sdcard/media_api/metadata/test35.mp4", - "/sdcard/media_api/metadata/test36.m4v", - "/sdcard/media_api/metadata/test34.wmv", - "/sdcard/media_api/metadata/test_metadata.mp4", - }; - - public static final String[] METADATA_RETRIEVAL_TEST_FILES = { - // Raw AAC is not supported - // "/sdcard/media_api/test_raw.aac", - // "/sdcard/media_api/test_adts.aac", - // "/sdcard/media_api/test_adif.aac", - "/sdcard/media_api/metadata/test_metadata.mp4", - "/sdcard/media_api/metadata/WMA10.wma", - "/sdcard/media_api/metadata/Leadsol_out.wav", - "/sdcard/media_api/metadata/test_aac.mp4", - "/sdcard/media_api/metadata/test_amr.mp4", - "/sdcard/media_api/metadata/test_avc_amr.mp4", - "/sdcard/media_api/metadata/test_metadata.mp4", - "/sdcard/media_api/metadata/test_vbr.mp3", - "/sdcard/media_api/metadata/test_cbr.mp3", - "/sdcard/media_api/metadata/metadata_test1.mp3", - "/sdcard/media_api/metadata/test33.3gp", - "/sdcard/media_api/metadata/test35.mp4", - "/sdcard/media_api/metadata/test36.m4v", - "/sdcard/media_api/metadata/test_m4v_amr.mp4", - "/sdcard/media_api/metadata/test_h263_amr.mp4", - "/sdcard/media_api/metadata/test34.wmv", - }; - - public static final String[] ALBUMART_TEST_FILES = { - "/sdcard/media_api/album_photo/test_22_16_mp3.mp3", - "/sdcard/media_api/album_photo/PD_256kbps_48khz_mono_CBR_MCA.mp3", - "/sdcard/media_api/album_photo/PD_256kbps_44.1khz_mono_CBR_DPA.mp3", - "/sdcard/media_api/album_photo/PD_192kbps_32khz_mono_CBR_DPA.mp3", - "/sdcard/media_api/album_photo/NIN_256kbps_48khz_mono_CBR_MCA.mp3", - "/sdcard/media_api/album_photo/NIN_256kbps_44.1khz_mono_CBR_MCA.mp3", - "/sdcard/media_api/album_photo/NIN_112kbps(96kbps)_48khz_stereo_VBR_MCA.mp3", - "/sdcard/media_api/album_photo/NIN_112kbps(96kbps)_44.1khz_stereo_VBR_MCA.mp3", - "/sdcard/media_api/album_photo/lightGreen1.mp3", - "/sdcard/media_api/album_photo/babyBlue2 1.mp3", - "/sdcard/media_api/album_photo/2-01 01 NIN_56kbps(64kbps)_32khz_stereo_VBR_MCA.mp3", - "/sdcard/media_api/album_photo/02_NIN_112kbps(80kbps)_32khz_stereo_VBR_MCA.mp3", - "/sdcard/media_api/album_photo/No_Woman_No_Cry_128K.wma", - "/sdcard/media_api/album_photo/Beethoven_2.wma", - }; - - //TEST_PATH_1: is a video and contains metadata for key "num-tracks" - // TEST_PATH_2: any valid media file. - // TEST_PATH_3: invalid media file - public static final String TEST_PATH_1 = "/sdcard/media_api/metadata/test.mp4"; - public static final String TEST_PATH_3 = "/sdcard/media_api/data.txt"; - public static final String TEST_PATH_4 = "somenonexistingpathname"; - public static final String TEST_PATH_5 = "mem://012345"; - - //Meta data expected result - //The expected tag result in the following order - //cd_track_number, album, artist, author, composer, date, genre - //title, years, duration - public static final String META_DATA_MP3 [][] = { - {"/sdcard/media_api/metaDataTestMedias/MP3/ID3V1_ID3V2.mp3", "1/10", "ID3V2.3 Album", "ID3V2.3 Artist", - "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, "Blues", - "ID3V2.3 Title", "1234", "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/ID3V2.mp3", "1/10", "ID3V2.3 Album", "ID3V2.3 Artist", - "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, "Blues", - "ID3V2.3 Title", "1234", "287", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/ID3V1.mp3", "1", "test ID3V1 Album", "test ID3V1 Artist", - null, null, null, "255", "test ID3V1 Title", "1234", "231332", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V1.mp3" , null, null, null, - null, null, null, null, null, null, "231330", "1", null}, - //The corrupted TALB field in id3v2 would not switch to id3v1 tag automatically - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TALB.mp3", "01", null, "ID3V2.3 Artist", - "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, - "Blues", "ID3V2.3 Title", "1234", "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TCOM.mp3", "01", "ID3V2.3 Album", - "ID3V2.3 Artist", "ID3V2.3 Lyricist", null, null, - "Blues", "ID3V2.3 Title", "1234", "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TCOM_2.mp3", "01", "ID3V2.3 Album", - "ID3V2.3 Artist", null, null, null, "Blues", "ID3V2.3 Title", "1234", "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TRCK.mp3", "dd", "ID3V2.3 Album", - "ID3V2.3 Artist", "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, - "Blues", "ID3V2.3 Title", "1234", "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TRCK_2.mp3", "01", "ID3V2.3 Album", - "ID3V2.3 Artist", null, null, null, null, "ID3V2.3 Title", null, "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TYER.mp3", "01", "ID3V2.3 Album", - "ID3V2.3 Artist", null, null, null, null, "ID3V2.3 Title", "9999", "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TYER_2.mp3", "01", "ID3V2.3 Album", - "ID3V2.3 Artist", "ID3V2.3 Lyricist", "ID3V2.3 Composer", null, - "Blues", "ID3V2.3 Title", null, "295", "1", null}, - {"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TIT.mp3", null, null, null, - null, null, null, null, null, null, "295", "1", null} - }; - - //output recorded video - - public static final String RECORDED_HVGA_H263 = "/sdcard/HVGA_H263.3gp"; - public static final String RECORDED_QVGA_H263 = "/sdcard/QVGA_H263.3gp"; - public static final String RECORDED_SQVGA_H263 = "/sdcard/SQVGA_H263.3gp"; - public static final String RECORDED_CIF_H263 = "/sdcard/CIF_H263.3gp"; - public static final String RECORDED_QCIF_H263 = "/sdcard/QCIF_H263.3gp"; - public static final String RECORDED_PORTRAIT_H263 = "/sdcard/QCIF_mp4.3gp"; - - public static final String RECORDED_HVGA_MP4 = "/sdcard/HVGA_mp4.mp4"; - public static final String RECORDED_QVGA_MP4 = "/sdcard/QVGA_mp4.mp4"; - public static final String RECORDED_SQVGA_MP4 = "/sdcard/SQVGA_mp4.mp4"; - public static final String RECORDED_CIF_MP4 = "/sdcard/CIF_mp4.mp4"; - public static final String RECORDED_QCIF_MP4 = "/sdcard/QCIF_mp4.mp4"; - - public static final String RECORDED_VIDEO_3GP = "/sdcard/temp.3gp"; - - public static final String INVALD_VIDEO_PATH = "/sdcard/media_api/filepathdoesnotexist" + - "/filepathdoesnotexist/temp.3gp"; - - - public static final long RECORDED_TIME = 5000; - public static final long VALID_VIDEO_DURATION = 2000; - - //Streaming test files - public static final byte [] STREAM_SERVER = new byte[] {(byte)75,(byte)17,(byte)48,(byte)204}; - public static final String STREAM_H264_480_360_1411k = - "http://75.17.48.204:10088/yslau/stress_media/h264_regular.mp4"; - public static final String STREAM_WMV = - "http://75.17.48.204:10088/yslau/stress_media/bugs.wmv"; - public static final String STREAM_H263_176x144_325k = - "http://75.17.48.204:10088/yslau/stress_media/h263_regular.3gp"; - public static final String STREAM_H264_352x288_1536k = - "http://75.17.48.204:10088/yslau/stress_media/h264_highBitRate.mp4"; - public static final String STREAM_MP3= - "http://75.17.48.204:10088/yslau/stress_media/mp3_regular.mp3"; - public static final String STREAM_MPEG4_QVGA_128k = - "http://75.17.48.204:10088/yslau/stress_media/mpeg4_qvga_24fps.3gp"; - public static final int STREAM_H264_480_360_1411k_DURATION = 46000; - public static final int VIDEO_H263_AAC_DURATION = 501000; - public static final int VIDEO_H263_AMR_DURATION = 502000; + + /* + * Metadata Utility Test media files which contain meta data. + */ + public static final String[] THUMBNAIL_METADATA_TEST_FILES = { + "/sdcard/media_api/video/H263_500_AMRNB_12.3gp", + "/sdcard/media_api/video/H263_56_AAC_24.3gp", + "/sdcard/media_api/video/H263_56_AMRNB_6.3gp", + "/sdcard/media_api/video/H264_320_AAC_64.3gp", + "/sdcard/media_api/video/H264_320_AMRNB_6.3gp", + "/sdcard/media_api/video/H264_500_AAC_128.3gp", + "/sdcard/media_api/video/H264_HVGA_500_NO_AUDIO.3gp", + "/sdcard/media_api/video/H264_QVGA_500_NO_AUDIO.3gp", + "/sdcard/media_api/video/MPEG4_320_AAC_64.mp4", + "/sdcard/media_api/video/border_large.3gp", + "/sdcard/media_api/videoeditor/H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4", + "/sdcard/media_api/videoeditor/H264_MP_960x720_25fps_800kbps_AACLC_48Khz_192Kbps_s_1_17.mp4", + "/sdcard/media_api/videoeditor/MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4", + "/sdcard/media_api/videoeditor/MPEG4_SP_176x144_12fps_92kbps_AMRNB_8KHz_12.2kbps_m_0_27.3gp", + "/sdcard/media_api/videoeditor/MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4" + }; + + public static final String[] ALBUMART_TEST_FILES = { + "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1_ID3V2.mp3", + "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V2.mp3", + "/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1.mp3", + }; + + // TEST_PATH_1: is a video and contains metadata for key "num-tracks" + // TEST_PATH_2: any valid media file. + // TEST_PATH_3: invalid media file + public static final String TEST_PATH_1 = "/sdcard/media_api/video/MPEG4_320_AAC_64.mp4"; + public static final String TEST_PATH_3 = "/sdcard/media_api/data.txt"; + public static final String TEST_PATH_4 = "somenonexistingpathname"; + public static final String TEST_PATH_5 = "mem://012345"; + + // Meta data expected result + // The expected tag result in the following order + // cd_track_number, album, artist, author, composer, date, genre + // title, years, duration + public static final String META_DATA_MP3[][] = { + {"/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1_ID3V2.mp3", "2/34", + "Test ID3V2 Album", "Test ID3V2 Artist", null, "Test ID3V2 Composer", + null, "(1)Classic Rock", "Test ID3V2 Title ", null, "77640", "1", null}, + {"/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V2.mp3", "1/10", + "Test ID3V2 Album", "Test ID3V2 Artist", null, "Test ID3V2 Composer", + null, "(74)Acid Jazz", "Test ID3V2 Tag", null, "77640", "1", null}, + {"/sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1.mp3", "2", + "Test ID3V1 Album", "Test ID3V1 Artist", null, null, null, "(15)", + "Test ID3V1 Title", "2011", "77640", "1", null} + }; + + // output recorded video + public static final String RECORDED_HVGA_H263 = "/sdcard/HVGA_H263.3gp"; + public static final String RECORDED_QVGA_H263 = "/sdcard/QVGA_H263.3gp"; + public static final String RECORDED_SQVGA_H263 = "/sdcard/SQVGA_H263.3gp"; + public static final String RECORDED_CIF_H263 = "/sdcard/CIF_H263.3gp"; + public static final String RECORDED_QCIF_H263 = "/sdcard/QCIF_H263.3gp"; + public static final String RECORDED_PORTRAIT_H263 = "/sdcard/QCIF_mp4.3gp"; + + public static final String RECORDED_HVGA_MP4 = "/sdcard/HVGA_mp4.mp4"; + public static final String RECORDED_QVGA_MP4 = "/sdcard/QVGA_mp4.mp4"; + public static final String RECORDED_SQVGA_MP4 = "/sdcard/SQVGA_mp4.mp4"; + public static final String RECORDED_CIF_MP4 = "/sdcard/CIF_mp4.mp4"; + public static final String RECORDED_QCIF_MP4 = "/sdcard/QCIF_mp4.mp4"; + + public static final String RECORDED_VIDEO_3GP = "/sdcard/temp.3gp"; + + public static final String INVALD_VIDEO_PATH = + "/sdcard/media_api/filepathdoesnotexist" + "/filepathdoesnotexist/temp.3gp"; + + public static final long RECORDED_TIME = 5000; + public static final long VALID_VIDEO_DURATION = 2000; + + // Streaming test files + public static final byte[] STREAM_SERVER = + new byte[] {(byte) 75, (byte) 17, (byte) 48, (byte) 204}; + public static final String STREAM_H264_480_360_1411k = + "http://75.17.48.204:10088/yslau/stress_media/h264_regular.mp4"; + public static final String STREAM_WMV = "http://75.17.48.204:10088/yslau/stress_media/bugs.wmv"; + public static final String STREAM_H263_176x144_325k = + "http://75.17.48.204:10088/yslau/stress_media/h263_regular.3gp"; + public static final String STREAM_H264_352x288_1536k = + "http://75.17.48.204:10088/yslau/stress_media/h264_highBitRate.mp4"; + public static final String STREAM_MP3 = + "http://75.17.48.204:10088/yslau/stress_media/mp3_regular.mp3"; + public static final String STREAM_MPEG4_QVGA_128k = + "http://75.17.48.204:10088/yslau/stress_media/mpeg4_qvga_24fps.3gp"; + public static final int STREAM_H264_480_360_1411k_DURATION = 46000; + public static final int VIDEO_H263_AAC_DURATION = 501000; + public static final int VIDEO_H263_AMR_DURATION = 502000; } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java index 00e0a52..380de9c 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java @@ -41,10 +41,7 @@ public class MediaMetadataTest extends AndroidTestCase { } public static enum MP3_TEST_FILE{ - ID3V1V2, ID3V2, ID3V1, - CORRUPTED_ID3V1, CORRUPTED_ID3V2_TALB, CORRUPTED_ID3V2_TCOM, - CORRUPTED_ID3V2_TCOM_2, CORRUPTED_ID3V2_TRCK, CORRUPTED_D3V2_TRCK_2, - CORRUPTED_ID3V2_TYER, CORRUPTED_ID3V2_TYER_2, CORRUPTED_ID3V2_TIT + ID3V1V2, ID3V2, ID3V1 } public static METADATA_EXPECTEDRESULT meta; @@ -64,53 +61,7 @@ public class MediaMetadataTest extends AndroidTestCase { public static void testID3V1Metadata() throws Exception { validateMetatData(mp3_test_file.ID3V1.ordinal(), MediaNames.META_DATA_MP3); } - - @MediumTest - public static void testCorruptedID3V1Metadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V1.ordinal(), MediaNames.META_DATA_MP3); - } - @MediumTest - public static void testCorrupted_ID3V2_TALBMetadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TALB.ordinal(), MediaNames.META_DATA_MP3); - } - - @MediumTest - public static void testCorrupted_ID3V2_TCOMMetadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TCOM.ordinal(), MediaNames.META_DATA_MP3); - } - - @MediumTest - public static void testCorrupted_ID3V2_TCOMM2etadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TCOM_2.ordinal(), MediaNames.META_DATA_MP3); - } - - @MediumTest - public static void testCorrupted_ID3V2_TRCKMetadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TRCK.ordinal(), MediaNames.META_DATA_MP3); - } - - @MediumTest - public static void testCorrupted_ID3V2_TRCK2Metadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_D3V2_TRCK_2.ordinal(), MediaNames.META_DATA_MP3); - } - - @MediumTest - public static void testCorrupted_ID3V2_TYERMetadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TYER.ordinal(), MediaNames.META_DATA_MP3); - } - - @MediumTest - public static void testCorrupted_ID3V2_TYER2Metadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TYER_2.ordinal(), MediaNames.META_DATA_MP3); - } - - @MediumTest - public static void testCorrupted_ID3V2_TITMetadata() throws Exception { - validateMetatData(mp3_test_file.CORRUPTED_ID3V2_TIT.ordinal(), MediaNames.META_DATA_MP3); - } - - private static void validateMetatData(int fileIndex, String meta_data_file[][]) { Log.v(TAG, "filePath = "+ meta_data_file[fileIndex][0]); if ((meta_data_file[fileIndex][0].endsWith("wma") && !MediaProfileReader.getWMAEnable()) || diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java index 3a9564d..57d5368 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java @@ -84,15 +84,6 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra duratoinWithinTolerence = verifyDuration(duration, MediaNames.MIDI_LENGTH); assertTrue("MIDI getDuration", duratoinWithinTolerence); } - - @MediumTest - public void testWMA9GetDuration() throws Exception { - if (isWMAEnable) { - int duration = CodecTest.getDuration(MediaNames.WMA9); - duratoinWithinTolerence = verifyDuration(duration, MediaNames.WMA9_LENGTH); - assertTrue("WMA9 getDuration", duratoinWithinTolerence); - } - } @MediumTest public void testAMRGetDuration() throws Exception { @@ -127,15 +118,7 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.MIDI); assertTrue("MIDI GetCurrentPosition", currentPosition); } - - @LargeTest - public void testWMA9GetCurrentPosition() throws Exception { - if (isWMAEnable) { - boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.WMA9); - assertTrue("WMA9 GetCurrentPosition", currentPosition); - } - } - + @LargeTest public void testAMRGetCurrentPosition() throws Exception { boolean currentPosition = CodecTest.getCurrentPosition(MediaNames.AMR); @@ -166,15 +149,7 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra boolean isPaused = CodecTest.pause(MediaNames.MIDI); assertTrue("MIDI Pause", isPaused); } - - @LargeTest - public void testWMA9Pause() throws Exception { - if (isWMAEnable) { - boolean isPaused = CodecTest.pause(MediaNames.WMA9); - assertTrue("WMA9 Pause", isPaused); - } - } - + @LargeTest public void testAMRPause() throws Exception { boolean isPaused = CodecTest.pause(MediaNames.AMR); @@ -239,15 +214,7 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra boolean isLoop = CodecTest.setLooping(MediaNames.MIDI); assertTrue("MIDI setLooping", isLoop); } - - @LargeTest - public void testWMA9SetLooping() throws Exception { - if (isWMAEnable) { - boolean isLoop = CodecTest.setLooping(MediaNames.WMA9); - assertTrue("WMA9 setLooping", isLoop); - } - } - + @LargeTest public void testAMRSetLooping() throws Exception { boolean isLoop = CodecTest.setLooping(MediaNames.AMR); @@ -279,15 +246,7 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra boolean isLoop = CodecTest.seekTo(MediaNames.MIDI); assertTrue("MIDI seekTo", isLoop); } - - @LargeTest - public void testWMA9SeekTo() throws Exception { - if (isWMAEnable) { - boolean isLoop = CodecTest.seekTo(MediaNames.WMA9); - assertTrue("WMA9 seekTo", isLoop); - } - } - + @LargeTest public void testAMRSeekTo() throws Exception { boolean isLoop = CodecTest.seekTo(MediaNames.AMR); @@ -320,15 +279,6 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra boolean isEnd = CodecTest.seekToEnd(MediaNames.MIDI); assertTrue("MIDI seekToEnd", isEnd); } - - @Suppress - @LargeTest - public void testWMA9SeekToEnd() throws Exception { - if (isWMAEnable) { - boolean isEnd = CodecTest.seekToEnd(MediaNames.WMA9); - assertTrue("WMA9 seekToEnd", isEnd); - } - } @LargeTest public void testAMRSeekToEnd() throws Exception { @@ -393,17 +343,13 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_H264_AMR); assertTrue("H264AMR SeekTo", isSeek); } - + @LargeTest - public void testVideoWMVSeekTo() throws Exception { - Log.v(TAG, "wmv not enable"); - if (isWMVEnable) { - Log.v(TAG, "wmv enable"); - boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_WMV); - assertTrue("WMV SeekTo", isSeek); - } + public void testVideoWebmSeekTo() throws Exception { + boolean isSeek = CodecTest.videoSeekTo(MediaNames.VIDEO_WEBM); + assertTrue("WEBM SeekTo", isSeek); } - + @LargeTest public void testSoundRecord() throws Exception { boolean isRecordered = CodecTest.mediaRecorderRecord(MediaNames.RECORDER_OUTPUT); @@ -412,7 +358,7 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFra @LargeTest public void testGetThumbnail() throws Exception { - boolean getThumbnail = CodecTest.getThumbnail(MediaNames.VIDEO_H264_AAC, MediaNames.GOLDEN_THUMBNAIL_OUTPUT_2); + boolean getThumbnail = CodecTest.getThumbnail(MediaNames.VIDEO_H264_AAC, MediaNames.GOLDEN_THUMBNAIL_OUTPUT); assertTrue("Get Thumbnail", getThumbnail); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java index 3b5b9a3..b396223 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java @@ -356,26 +356,6 @@ public class MediaPlayerPerformance extends ActivityInstrumentationTestCase2<Med assertTrue("H264 playback memory test", memoryResult); } - // Test case 3: Capture the memory usage after each 20 WMV playback - @LargeTest - public void testWMVVideoPlaybackMemoryUsage() throws Exception { - boolean memoryResult = false; - if (MediaProfileReader.getWMVEnable()){ - mStartPid = getMediaserverPid(); - File wmvMemoryOut = new File(MEDIA_MEMORY_OUTPUT); - Writer output = new BufferedWriter(new FileWriter(wmvMemoryOut, true)); - output.write("WMV video playback only\n"); - for (int i = 0; i < NUM_STRESS_LOOP; i++) { - mediaStressPlayback(MediaNames.VIDEO_WMV); - getMemoryWriteToLog(output, i); - } - output.write("\n"); - memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT); - output.close(); - assertTrue("wmv playback memory test", memoryResult); - } - } - // Test case 4: Capture the memory usage after every 20 video only recorded @LargeTest public void testH263RecordVideoOnlyMemoryUsage() throws Exception { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java index a66db05..8eb75f3 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java @@ -76,29 +76,29 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { boolean hasFailed = false; Log.v(TAG, "Thumbnail processing starts"); long startedAt = System.currentTimeMillis(); - for(int i = 0, n = MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length; i < n; ++i) { + for(int i = 0, n = MediaNames.THUMBNAIL_METADATA_TEST_FILES.length; i < n; ++i) { try { - Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]); - if ((MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i].endsWith(".wma") && !supportWMA) || - (MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i].endsWith(".wmv") && !supportWMV) + Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); + if ((MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wma") && !supportWMA) || + (MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wmv") && !supportWMV) ) { Log.v(TAG, "windows media is not supported and thus we will skip the test for this file"); continue; } - retriever.setDataSource(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]); + retriever.setDataSource(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); Bitmap bitmap = retriever.getFrameAtTime(-1); assertTrue(bitmap != null); try { - java.io.OutputStream stream = new FileOutputStream(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i] + ".jpg"); + java.io.OutputStream stream = new FileOutputStream(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i] + ".jpg"); bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream); stream.close(); } catch (Exception e) { - Log.e(TAG, "Fails to convert the bitmap to a JPEG file for " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]); + Log.e(TAG, "Fails to convert the bitmap to a JPEG file for " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); hasFailed = true; Log.e(TAG, e.toString()); } } catch(Exception e) { - Log.e(TAG, "Fails to setDataSource for file " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]); + Log.e(TAG, "Fails to setDataSource for file " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); hasFailed = true; } Thread.yield(); // Don't be evil @@ -106,7 +106,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { long endedAt = System.currentTimeMillis(); retriever.release(); assertTrue(!hasFailed); - Log.v(TAG, "Average processing time per thumbnail: " + (endedAt - startedAt)/MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length + " ms"); + Log.v(TAG, "Average processing time per thumbnail: " + (endedAt - startedAt)/MediaNames.THUMBNAIL_METADATA_TEST_FILES.length + " ms"); } @LargeTest @@ -115,19 +115,19 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { boolean supportWMV = MediaProfileReader.getWMVEnable(); boolean hasFailed = false; MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) { + for(int i = 0, n = MediaNames.THUMBNAIL_METADATA_TEST_FILES.length; i < n; ++i) { try { - Log.v(TAG, "File " + i + ": " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]); - if ((MediaNames.METADATA_RETRIEVAL_TEST_FILES[i].endsWith(".wma") && !supportWMA) || - (MediaNames.METADATA_RETRIEVAL_TEST_FILES[i].endsWith(".wmv") && !supportWMV) + Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); + if ((MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wma") && !supportWMA) || + (MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wmv") && !supportWMV) ) { Log.v(TAG, "windows media is not supported and thus we will skip the test for this file"); continue; } - retriever.setDataSource(MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]); + retriever.setDataSource(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); extractAllSupportedMetadataValues(retriever); } catch(Exception e) { - Log.e(TAG, "Fails to setDataSource for file " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]); + Log.e(TAG, "Fails to setDataSource for file " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); hasFailed = true; } Thread.yield(); // Don't be evil @@ -239,45 +239,6 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { assertTrue(!hasFailed); } - @MediumTest - public static void testIntendedUsage() { - // By default, capture frame and retrieve metadata - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - boolean hasFailed = false; - retriever.setDataSource(MediaNames.TEST_PATH_1); - assertTrue(retriever.getFrameAtTime(-1) != null); - assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null); - - // Do not capture frame or retrieve metadata - retriever.setDataSource(MediaNames.TEST_PATH_1); - if (retriever.getFrameAtTime(-1) != null) { - Log.e(TAG, "No frame expected, but is available"); - hasFailed = true; - } - if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null) { - Log.e(TAG, "No num track metadata expected, but is available"); - hasFailed = true; - } - - // Capture frame only - retriever.setDataSource(MediaNames.TEST_PATH_1); - assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null); - - // Retriever metadata only - retriever.setDataSource(MediaNames.TEST_PATH_1); - if (retriever.getFrameAtTime(-1) != null) { - Log.e(TAG, "No frame expected, but is available"); - hasFailed = true; - } - - // Capture frame and retrieve metadata - retriever.setDataSource(MediaNames.TEST_PATH_1); - assertTrue(retriever.getFrameAtTime(-1) != null); - assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null); - retriever.release(); - assertTrue(!hasFailed); - } - // TODO: // Encode and test for the correct mix of metadata elements on a per-file basis? // We should be able to compare the actual returned metadata with the expected metadata diff --git a/media/tests/contents/media_api/goldenThumbnail.png b/media/tests/contents/media_api/goldenThumbnail.png Binary files differnew file mode 100755 index 0000000..3bb6ed2 --- /dev/null +++ b/media/tests/contents/media_api/goldenThumbnail.png diff --git a/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17.mp3 b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17.mp3 Binary files differnew file mode 100755 index 0000000..e0d6a17 --- /dev/null +++ b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17.mp3 diff --git a/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ABR.mp3 b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ABR.mp3 Binary files differnew file mode 100644 index 0000000..12f7193 --- /dev/null +++ b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ABR.mp3 diff --git a/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3 b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3 Binary files differnew file mode 100644 index 0000000..12f7193 --- /dev/null +++ b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3 diff --git a/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1.mp3 b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1.mp3 Binary files differnew file mode 100644 index 0000000..29d332b --- /dev/null +++ b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1.mp3 diff --git a/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1_ID3V2.mp3 b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1_ID3V2.mp3 Binary files differnew file mode 100644 index 0000000..ea52638 --- /dev/null +++ b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V1_ID3V2.mp3 diff --git a/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V2.mp3 b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V2.mp3 Binary files differnew file mode 100644 index 0000000..024039c --- /dev/null +++ b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_ID3V2.mp3 diff --git a/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_VBR.mp3 b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_VBR.mp3 Binary files differnew file mode 100644 index 0000000..12f7193 --- /dev/null +++ b/media/tests/contents/media_api/music/MP3_48KHz_128kbps_s_1_17_VBR.mp3 diff --git a/media/tests/contents/media_api/music/SHORTMP3.mp3 b/media/tests/contents/media_api/music/SHORTMP3.mp3 Binary files differnew file mode 100755 index 0000000..8b51b5d --- /dev/null +++ b/media/tests/contents/media_api/music/SHORTMP3.mp3 diff --git a/media/tests/contents/media_api/music/ants.mid b/media/tests/contents/media_api/music/ants.mid Binary files differnew file mode 100755 index 0000000..d4ead53 --- /dev/null +++ b/media/tests/contents/media_api/music/ants.mid diff --git a/media/tests/contents/media_api/music/bzk_chic.wav b/media/tests/contents/media_api/music/bzk_chic.wav Binary files differnew file mode 100755 index 0000000..bab1a6b --- /dev/null +++ b/media/tests/contents/media_api/music/bzk_chic.wav diff --git a/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav Binary files differnew file mode 100755 index 0000000..312b6fb --- /dev/null +++ b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav diff --git a/media/tests/contents/media_api/music/test_amr_ietf.amr b/media/tests/contents/media_api/music/test_amr_ietf.amr Binary files differnew file mode 100755 index 0000000..540794c --- /dev/null +++ b/media/tests/contents/media_api/music/test_amr_ietf.amr diff --git a/media/tests/contents/media_api/video/big-buck-bunny_trailer.webm b/media/tests/contents/media_api/video/big-buck-bunny_trailer.webm Binary files differnew file mode 100755 index 0000000..6a17395 --- /dev/null +++ b/media/tests/contents/media_api/video/big-buck-bunny_trailer.webm diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index 72209f6..f385a23 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -114,7 +114,15 @@ public class KeyguardUpdateMonitor { } String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE); if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { - this.simState = IccCard.State.ABSENT; + final String absentReason = intent + .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON); + + if (IccCard.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals( + absentReason)) { + this.simState = IccCard.State.PERM_DISABLED; + } else { + this.simState = IccCard.State.ABSENT; + } } else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) { this.simState = IccCard.State.READY; } else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 8a60098..8ba235b 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -580,7 +580,9 @@ public class KeyguardViewMediator implements KeyguardViewCallback, final boolean provisioned = mUpdateMonitor.isDeviceProvisioned(); final IccCard.State state = mUpdateMonitor.getSimState(); final boolean lockedOrMissing = state.isPinLocked() - || ((state == IccCard.State.ABSENT) && requireSim); + || ((state == IccCard.State.ABSENT + || state == IccCard.State.PERM_DISABLED) + && requireSim); if (!lockedOrMissing && !provisioned) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned" @@ -687,12 +689,15 @@ public class KeyguardViewMediator implements KeyguardViewCallback, switch (simState) { case ABSENT: + case PERM_DISABLED: // only force lock screen in case of missing sim if user hasn't // gone through setup wizard if (!mUpdateMonitor.isDeviceProvisioned()) { if (!isShowing()) { - if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_ABSENT and keygaurd isn't showing, we need " - + "to show the keyguard since the device isn't provisioned yet."); + if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_ABSENT " + + "or PERM_DISABLED and keygaurd isn't showing," + + " we need to show the keyguard since the " + + "device isn't provisioned yet."); doKeyguard(); } else { resetStateLocked(); diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 874acd0..eea3040 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -181,7 +181,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase { private boolean stuckOnLockScreenBecauseSimMissing() { return mRequiresSim && (!mUpdateMonitor.isDeviceProvisioned()) - && (mUpdateMonitor.getSimState() == IccCard.State.ABSENT); + && (mUpdateMonitor.getSimState() == IccCard.State.ABSENT || + mUpdateMonitor.getSimState() == IccCard.State.PERM_DISABLED); } /** diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java index ed5a058..19adb3e 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java @@ -55,8 +55,10 @@ public class LockPatternKeyguardViewProperties implements KeyguardViewProperties private boolean isSimPinSecure() { final IccCard.State simState = mUpdateMonitor.getSimState(); - return (simState == IccCard.State.PIN_REQUIRED || simState == IccCard.State.PUK_REQUIRED - || simState == IccCard.State.ABSENT); + return (simState == IccCard.State.PIN_REQUIRED + || simState == IccCard.State.PUK_REQUIRED + || simState == IccCard.State.ABSENT + || simState == IccCard.State.PERM_DISABLED); } } diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 08f9ebb..8b7a61e 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -129,7 +129,12 @@ class LockScreen extends LinearLayout implements KeyguardScreen, /** * The sim card is locked. */ - SimLocked(true); + SimLocked(true), + + /** + * The sim card is permanently disabled due to puk unlock failure + */ + SimPermDisabled(false); private final boolean mShowStatusLines; @@ -503,7 +508,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen, */ private Status getCurrentStatus(IccCard.State simState) { boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned() - && simState == IccCard.State.ABSENT); + && (simState == IccCard.State.ABSENT + || simState == IccCard.State.PERM_DISABLED)); + if (missingAndNotProvisioned) { return Status.SimMissingLocked; } @@ -521,6 +528,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen, return Status.SimPukLocked; case READY: return Status.Normal; + case PERM_DISABLED: + return Status.SimPermDisabled; case UNKNOWN: return Status.SimMissing; } @@ -595,6 +604,18 @@ class LockScreen extends LinearLayout implements KeyguardScreen, enableUnlock(); // do not need to show the e-call button; user may unlock break; + case SimPermDisabled: + // text + mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short); + mScreenLocked.setText( + R.string.lockscreen_permanent_disabled_sim_instructions); + + // layout + mScreenLocked.setVisibility(View.VISIBLE); + mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText); + enableUnlock(); // do not need to show the e-call button; user may unlock + break; + case SimMissingLocked: // text mStatusView.setCarrierText( diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 1e8c30b..a011ae2 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -147,6 +147,14 @@ sp<ICamera> CameraService::connect( return NULL; } + char value[PROPERTY_VALUE_MAX]; + property_get("sys.secpolicy.camera.disabled", value, "0"); + if (strcmp(value, "1") == 0) { + // Camera is disabled by DevicePolicyManager. + LOGI("Camera is disabled. connect X (pid %d) rejected", callingPid); + return NULL; + } + Mutex::Autolock lock(mServiceLock); if (mClient[cameraId] != 0) { client = mClient[cameraId].promote(); diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index fd502d8..158c778 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -395,41 +395,47 @@ class AppWidgetService extends IAppWidgetService.Stub public void bindAppWidgetId(int appWidgetId, ComponentName provider) { mContext.enforceCallingPermission(android.Manifest.permission.BIND_APPWIDGET, "bindGagetId appWidgetId=" + appWidgetId + " provider=" + provider); - synchronized (mAppWidgetIds) { - AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); - if (id == null) { - throw new IllegalArgumentException("bad appWidgetId"); - } - if (id.provider != null) { - throw new IllegalArgumentException("appWidgetId " + appWidgetId + " already bound to " - + id.provider.info.provider); - } - Provider p = lookupProviderLocked(provider); - if (p == null) { - throw new IllegalArgumentException("not a appwidget provider: " + provider); - } - if (p.zombie) { - throw new IllegalArgumentException("can't bind to a 3rd party provider in" - + " safe mode: " + provider); - } - - id.provider = p; - p.instances.add(id); - int instancesSize = p.instances.size(); - if (instancesSize == 1) { - // tell the provider that it's ready - sendEnableIntentLocked(p); + + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mAppWidgetIds) { + AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); + if (id == null) { + throw new IllegalArgumentException("bad appWidgetId"); + } + if (id.provider != null) { + throw new IllegalArgumentException("appWidgetId " + appWidgetId + " already bound to " + + id.provider.info.provider); + } + Provider p = lookupProviderLocked(provider); + if (p == null) { + throw new IllegalArgumentException("not a appwidget provider: " + provider); + } + if (p.zombie) { + throw new IllegalArgumentException("can't bind to a 3rd party provider in" + + " safe mode: " + provider); + } + + id.provider = p; + p.instances.add(id); + int instancesSize = p.instances.size(); + if (instancesSize == 1) { + // tell the provider that it's ready + sendEnableIntentLocked(p); + } + + // send an update now -- We need this update now, and just for this appWidgetId. + // It's less critical when the next one happens, so when we schdule the next one, + // we add updatePeriodMillis to its start time. That time will have some slop, + // but that's okay. + sendUpdateIntentLocked(p, new int[] { appWidgetId }); + + // schedule the future updates + registerForBroadcastsLocked(p, getAppWidgetIds(p)); + saveStateLocked(); } - - // send an update now -- We need this update now, and just for this appWidgetId. - // It's less critical when the next one happens, so when we schdule the next one, - // we add updatePeriodMillis to its start time. That time will have some slop, - // but that's okay. - sendUpdateIntentLocked(p, new int[] { appWidgetId }); - - // schedule the future updates - registerForBroadcastsLocked(p, getAppWidgetIds(p)); - saveStateLocked(); + } finally { + Binder.restoreCallingIdentity(ident); } } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index c6f4c20..07855d9 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -16,8 +16,7 @@ package com.android.server; -import static android.Manifest.permission.READ_PHONE_STATE; -import static android.Manifest.permission.UPDATE_DEVICE_STATS; +import static android.Manifest.permission.MANAGE_NETWORK_POLICY; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_PAID; @@ -48,7 +47,6 @@ import android.net.RouteInfo; import android.net.vpn.VpnManager; import android.net.wifi.WifiStateTracker; import android.os.Binder; -import android.os.Bundle; import android.os.FileUtils; import android.os.Handler; import android.os.HandlerThread; @@ -67,6 +65,7 @@ import android.util.EventLog; import android.util.Slog; import android.util.SparseIntArray; +import com.android.internal.net.VpnConfig; import com.android.internal.telephony.Phone; import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; @@ -1142,8 +1141,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { @Override public void onRulesChanged(int uid, int uidRules) { // only someone like NPMS should only be calling us - // TODO: create permission for modifying data policy - mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG); + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); if (LOGD_RULES) { Slog.d(TAG, "onRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")"); @@ -1267,8 +1265,30 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); + + // Reset interface if no other connections are using the same interface + boolean doReset = true; + LinkProperties linkProperties = mNetTrackers[prevNetType].getLinkProperties(); + if (linkProperties != null) { + String oldIface = linkProperties.getInterfaceName(); + if (TextUtils.isEmpty(oldIface) == false) { + for (NetworkStateTracker networkStateTracker : mNetTrackers) { + if (networkStateTracker == null) continue; + NetworkInfo networkInfo = networkStateTracker.getNetworkInfo(); + if (networkInfo.isConnected() && networkInfo.getType() != prevNetType) { + LinkProperties l = networkStateTracker.getLinkProperties(); + if (l == null) continue; + if (oldIface.equals(l.getInterfaceName())) { + doReset = false; + break; + } + } + } + } + } + // do this before we broadcast the change - handleConnectivityChange(prevNetType); + handleConnectivityChange(prevNetType, doReset); sendStickyBroadcast(intent); /* @@ -1490,7 +1510,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } thisNet.setTeardownRequested(false); updateNetworkSettings(thisNet); - handleConnectivityChange(type); + handleConnectivityChange(type, false); sendConnectedBroadcast(info); } @@ -1500,7 +1520,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { * according to which networks are connected, and ensuring that the * right routing table entries exist. */ - private void handleConnectivityChange(int netType) { + private void handleConnectivityChange(int netType, boolean doReset) { /* * If a non-default network is enabled, add the host routes that * will allow it's DNS servers to be accessed. @@ -1540,6 +1560,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { removePrivateDnsRoutes(mNetTrackers[netType]); } } + + if (doReset) { + LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties(); + if (linkProperties != null) { + String iface = linkProperties.getInterfaceName(); + if (TextUtils.isEmpty(iface) == false) { + if (DBG) log("resetConnections(" + iface + ")"); + NetworkUtils.resetConnections(iface); + } + } + } } private void addPrivateDnsRoutes(NetworkStateTracker nt) { @@ -1965,7 +1996,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { break; case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: info = (NetworkInfo) msg.obj; - handleConnectivityChange(info.getType()); + handleConnectivityChange(info.getType(), true); break; case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: String causedBy = null; @@ -2396,24 +2427,37 @@ public class ConnectivityService extends IConnectivityManager.Stub { return value; } - // @see ConnectivityManager#protectVpn(ParcelFileDescriptor) - // Permission checks are done in Vpn class. + /** + * Protect a socket from VPN routing rules. This method is used by + * VpnBuilder and not available in ConnectivityManager. Permission + * checks are done in Vpn class. + * @hide + */ @Override public void protectVpn(ParcelFileDescriptor socket) { mVpn.protect(socket, getDefaultInterface()); } - // @see ConnectivityManager#prepareVpn(String) - // Permission checks are done in Vpn class. + /** + * Prepare for a VPN application. This method is used by VpnDialogs + * and not available in ConnectivityManager. Permission checks are + * done in Vpn class. + * @hide + */ @Override public String prepareVpn(String packageName) { return mVpn.prepare(packageName); } - // @see ConnectivityManager#establishVpn(Bundle) - // Permission checks are done in Vpn class. + /** + * Configure a TUN interface and return its file descriptor. Parameters + * are encoded and opaque to this class. This method is used by VpnBuilder + * and not available in ConnectivityManager. Permission checks are done + * in Vpn class. + * @hide + */ @Override - public ParcelFileDescriptor establishVpn(Bundle config) { + public ParcelFileDescriptor establishVpn(VpnConfig config) { return mVpn.establish(config); } diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index 941ab80..372ba85 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -29,12 +29,12 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.net.INetworkManagementEventObserver; import android.os.Binder; -import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; import com.android.internal.R; +import com.android.internal.net.VpnConfig; import com.android.server.ConnectivityService.VpnCallback; /** @@ -108,7 +108,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { * @param configuration The parameters to configure the interface. * @return The file descriptor of the interface. */ - public synchronized ParcelFileDescriptor establish(Bundle config) { + public synchronized ParcelFileDescriptor establish(VpnConfig config) { // Check the permission of the caller. mContext.enforceCallingPermission(VPN, "establish"); @@ -124,17 +124,9 @@ public class Vpn extends INetworkManagementEventObserver.Stub { throw new SecurityException("Not prepared"); } - // Unpack the config. - // TODO: move constants into VpnBuilder. - int mtu = config.getInt("mtu", -1); - String session = config.getString("session"); - String addresses = config.getString("addresses"); - String routes = config.getString("routes"); - String dnsServers = config.getString("dnsServers"); - // Create and configure the interface. - ParcelFileDescriptor descriptor = - ParcelFileDescriptor.adoptFd(nativeEstablish(mtu, addresses, routes)); + ParcelFileDescriptor descriptor = ParcelFileDescriptor.adoptFd( + nativeEstablish(config.mtu, config.addresses, config.routes)); // Replace the interface and abort if it fails. try { @@ -153,10 +145,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub { throw e; } - dnsServers = (dnsServers == null) ? "" : dnsServers.trim(); + String dnsServers = (config.dnsServers == null) ? "" : config.dnsServers.trim(); mCallback.override(dnsServers.isEmpty() ? null : dnsServers.split(" ")); - showNotification(pm, app, session); + showNotification(pm, app, config.sessionName); return descriptor; } diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index dac0044..9cbe82d 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -747,6 +747,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @Override public void registerListener(INetworkPolicyListener listener) { + // TODO: create permission for observing network policy + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + mListeners.register(listener); synchronized (mRulesLock) { @@ -767,6 +770,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @Override public void unregisterListener(INetworkPolicyListener listener) { + // TODO: create permission for observing network policy + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + mListeners.unregister(listener); } diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 151fde7..ee5f3f5 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -28,6 +28,7 @@ <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" /> <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" /> <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" /> + <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java index 5d8fc78..02617c8 100644 --- a/telephony/java/com/android/internal/telephony/IccCard.java +++ b/telephony/java/com/android/internal/telephony/IccCard.java @@ -84,6 +84,9 @@ public abstract class IccCard { static public final String INTENT_VALUE_LOCKED_ON_PUK = "PUK"; /* NETWORK means ICC is locked on NETWORK PERSONALIZATION */ static public final String INTENT_VALUE_LOCKED_NETWORK = "NETWORK"; + /* PERM_DISABLED means ICC is permanently disabled due to puk fails */ + static public final String INTENT_VALUE_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED"; + protected static final int EVENT_ICC_LOCKED_OR_ABSENT = 1; private static final int EVENT_GET_ICC_STATUS_DONE = 2; @@ -112,7 +115,8 @@ public abstract class IccCard { PUK_REQUIRED, NETWORK_LOCKED, READY, - NOT_READY; + NOT_READY, + PERM_DISABLED; public boolean isPinLocked() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)); @@ -120,7 +124,8 @@ public abstract class IccCard { public boolean iccCardExist() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED) - || (this == NETWORK_LOCKED) || (this == READY)); + || (this == NETWORK_LOCKED) || (this == READY) + || (this == PERM_DISABLED)); } } @@ -416,6 +421,7 @@ public abstract class IccCard { boolean transitionedIntoPinLocked; boolean transitionedIntoAbsent; boolean transitionedIntoNetworkLocked; + boolean transitionedIntoPermBlocked; boolean isIccCardRemoved; boolean isIccCardAdded; @@ -434,6 +440,8 @@ public abstract class IccCard { transitionedIntoAbsent = (oldState != State.ABSENT && newState == State.ABSENT); transitionedIntoNetworkLocked = (oldState != State.NETWORK_LOCKED && newState == State.NETWORK_LOCKED); + transitionedIntoPermBlocked = (oldState != State.PERM_DISABLED + && newState == State.PERM_DISABLED); isIccCardRemoved = (oldState != null && oldState.iccCardExist() && newState == State.ABSENT); isIccCardAdded = (oldState == State.ABSENT && @@ -454,6 +462,10 @@ public abstract class IccCard { mNetworkLockedRegistrants.notifyRegistrants(); broadcastIccStateChangedIntent(INTENT_VALUE_ICC_LOCKED, INTENT_VALUE_LOCKED_NETWORK); + } else if (transitionedIntoPermBlocked) { + if (mDbg) log("Notify SIM permanently disabled."); + broadcastIccStateChangedIntent(INTENT_VALUE_ICC_ABSENT, + INTENT_VALUE_ABSENT_ON_PERM_DISABLED); } if (isIccCardRemoved) { @@ -762,6 +774,9 @@ public abstract class IccCard { } // check if PIN required + if (app.pin1.isPermBlocked()) { + return IccCard.State.PERM_DISABLED; + } if (app.app_state.isPinRequired()) { return IccCard.State.PIN_REQUIRED; } diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java index 434c484..abb740e 100644 --- a/telephony/java/com/android/internal/telephony/IccCardApplication.java +++ b/telephony/java/com/android/internal/telephony/IccCardApplication.java @@ -16,6 +16,8 @@ package com.android.internal.telephony; +import com.android.internal.telephony.IccCardStatus.PinState; + /** * See also RIL_AppStatus in include/telephony/ril.h @@ -104,8 +106,8 @@ public class IccCardApplication { public String app_label; // applicable to USIM and CSIM public int pin1_replaced; - public int pin1; - public int pin2; + public PinState pin1; + public PinState pin2; AppType AppTypeFromRILInt(int type) { AppType newType; @@ -177,6 +179,33 @@ public class IccCardApplication { return newSubState; } + PinState PinStateFromRILInt(int state) { + PinState newPinState; + switch(state) { + case 0: + newPinState = PinState.PINSTATE_UNKNOWN; + break; + case 1: + newPinState = PinState.PINSTATE_ENABLED_NOT_VERIFIED; + break; + case 2: + newPinState = PinState.PINSTATE_ENABLED_VERIFIED; + break; + case 3: + newPinState = PinState.PINSTATE_DISABLED; + break; + case 4: + newPinState = PinState.PINSTATE_ENABLED_BLOCKED; + break; + case 5: + newPinState = PinState.PINSTATE_ENABLED_PERM_BLOCKED; + break; + default: + throw new RuntimeException("Unrecognized RIL_PinState: " + state); + } + return newPinState; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -185,6 +214,12 @@ public class IccCardApplication { if (app_state == AppState.APPSTATE_SUBSCRIPTION_PERSO) { sb.append(",").append(perso_substate); } + if (app_type == AppType.APPTYPE_CSIM || + app_type == AppType.APPTYPE_USIM || + app_type == AppType.APPTYPE_ISIM) { + sb.append(",pin1=").append(pin1); + sb.append(",pin2=").append(pin2); + } sb.append("}"); return sb.toString(); } diff --git a/telephony/java/com/android/internal/telephony/IccCardStatus.java b/telephony/java/com/android/internal/telephony/IccCardStatus.java index e9de922..c751a21 100644 --- a/telephony/java/com/android/internal/telephony/IccCardStatus.java +++ b/telephony/java/com/android/internal/telephony/IccCardStatus.java @@ -42,7 +42,19 @@ public class IccCardStatus { PINSTATE_ENABLED_VERIFIED, PINSTATE_DISABLED, PINSTATE_ENABLED_BLOCKED, - PINSTATE_ENABLED_PERM_BLOCKED + PINSTATE_ENABLED_PERM_BLOCKED; + + boolean isPermBlocked() { + return this == PINSTATE_ENABLED_PERM_BLOCKED; + } + + boolean isPinRequired() { + return this == PINSTATE_ENABLED_NOT_VERIFIED; + } + + boolean isPukRequired() { + return this == PINSTATE_ENABLED_BLOCKED; + } } private CardState mCardState; diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index 572bbaa..76f1ab7 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -2924,8 +2924,8 @@ public final class RIL extends BaseCommands implements CommandsInterface { ca.aid = p.readString(); ca.app_label = p.readString(); ca.pin1_replaced = p.readInt(); - ca.pin1 = p.readInt(); - ca.pin2 = p.readInt(); + ca.pin1 = ca.PinStateFromRILInt(p.readInt()); + ca.pin2 = ca.PinStateFromRILInt(p.readInt()); status.addApplication(ca); } return status; diff --git a/tests/RenderScriptTests/FBOTest/AndroidManifest.xml b/tests/RenderScriptTests/FBOTest/AndroidManifest.xml index c2e0cc6..788e856 100644 --- a/tests/RenderScriptTests/FBOTest/AndroidManifest.xml +++ b/tests/RenderScriptTests/FBOTest/AndroidManifest.xml @@ -3,11 +3,20 @@ package="com.android.fbotest"> <application android:label="_FBOTest"> <activity android:name="FBOTest" + android:label="FBO Base Test" 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> + </activity> + <activity android:name="FBOSync" + android:label="FBO Sync Test" + 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/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSync.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSync.java new file mode 100644 index 0000000..d30ad7e --- /dev/null +++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSync.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.fbotest; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; + +import android.app.Activity; +import android.content.res.Configuration; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings.System; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.MenuInflater; +import android.view.Window; +import android.widget.Button; +import android.widget.ListView; +import android.net.Uri; + +import java.lang.Runtime; + +public class FBOSync extends Activity { + + private FBOSyncView 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 FBOSyncView(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.resume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mView.pause(); + } +} + diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncRS.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncRS.java new file mode 100644 index 0000000..57a117c --- /dev/null +++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncRS.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.fbotest; + +import java.io.Writer; + +import android.content.res.Resources; +import android.renderscript.*; +import android.renderscript.Element.DataType; +import android.renderscript.Element.DataKind; +import android.renderscript.ProgramStore.DepthFunc; +import android.renderscript.Type.Builder; +import android.util.Log; + + +public class FBOSyncRS { + + public FBOSyncRS() { + } + + public void init(RenderScriptGL rs, Resources res) { + mRS = rs; + mRes = res; + initRS(); + } + + public void surfaceChanged() { + mRS.getWidth(); + mRS.getHeight(); + } + + private Resources mRes; + private RenderScriptGL mRS; + private Sampler mSampler; + private ProgramStore mPSBackground; + private ProgramFragment mPFBackground; + private ProgramVertex mPVBackground; + private ProgramVertexFixedFunction.Constants mPVA; + + private Allocation mGridImage; + private Allocation mOffscreen; + private Allocation mOffscreenDepth; + private Allocation mAllocPV; + private Allocation mReadBackTest; + + private Font mItalic; + private Allocation mTextAlloc; + + private ScriptField_MeshInfo mMeshes; + private ScriptC_fbosync mScript; + + + public void onActionDown(float x, float y) { + mScript.invoke_onActionDown(x, y); + } + + public void onActionScale(float scale) { + mScript.invoke_onActionScale(scale); + } + + public void onActionMove(float x, float y) { + mScript.invoke_onActionMove(x, y); + } + + private void initPFS() { + ProgramStore.Builder b = new ProgramStore.Builder(mRS); + + b.setDepthFunc(ProgramStore.DepthFunc.LESS); + b.setDitherEnabled(false); + b.setDepthMaskEnabled(true); + mPSBackground = b.create(); + + mScript.set_gPFSBackground(mPSBackground); + } + + private void initPF() { + Sampler.Builder bs = new Sampler.Builder(mRS); + bs.setMinification(Sampler.Value.LINEAR); + bs.setMagnification(Sampler.Value.LINEAR); + bs.setWrapS(Sampler.Value.CLAMP); + bs.setWrapT(Sampler.Value.CLAMP); + mSampler = bs.create(); + + ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS); + b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + mPFBackground = b.create(); + mPFBackground.bindSampler(mSampler, 0); + + mScript.set_gPFBackground(mPFBackground); + } + + private void initPV() { + ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); + mPVBackground = pvb.create(); + + mPVA = new ProgramVertexFixedFunction.Constants(mRS); + ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA); + + mScript.set_gPVBackground(mPVBackground); + } + + private void loadImage() { + mGridImage = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot, + Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, + Allocation.USAGE_GRAPHICS_TEXTURE); + mScript.set_gTGrid(mGridImage); + } + + private void initTextAllocation(String fileName) { + String allocString = "Displaying file: " + fileName; + mTextAlloc = Allocation.createFromString(mRS, allocString, Allocation.USAGE_SCRIPT); + mScript.set_gTextAlloc(mTextAlloc); + } + + private void initMeshes(FileA3D model) { + int numEntries = model.getIndexEntryCount(); + int numMeshes = 0; + for (int i = 0; i < numEntries; i ++) { + FileA3D.IndexEntry entry = model.getIndexEntry(i); + if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) { + numMeshes ++; + } + } + + if (numMeshes > 0) { + mMeshes = new ScriptField_MeshInfo(mRS, numMeshes); + + for (int i = 0; i < numEntries; i ++) { + FileA3D.IndexEntry entry = model.getIndexEntry(i); + if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) { + Mesh mesh = entry.getMesh(); + mMeshes.set_mMesh(i, mesh, false); + mMeshes.set_mNumIndexSets(i, mesh.getPrimitiveCount(), false); + } + } + mMeshes.copyAll(); + } else { + throw new RSRuntimeException("No valid meshes in file"); + } + + mScript.bind_gMeshes(mMeshes); + mScript.invoke_updateMeshInfo(); + } + + public void loadA3DFile(String path) { + FileA3D model = FileA3D.createFromFile(mRS, path); + initMeshes(model); + initTextAllocation(path); + } + + private void initRS() { + + mScript = new ScriptC_fbosync(mRS, mRes, R.raw.fbosync); + + initPFS(); + initPF(); + initPV(); + + loadImage(); + + Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS)); + b.setX(512).setY(512); + mOffscreen = Allocation.createTyped(mRS, + b.create(), + Allocation.USAGE_SCRIPT | + Allocation.USAGE_GRAPHICS_TEXTURE | + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + mScript.set_gOffscreen(mOffscreen); + + mReadBackTest = Allocation.createTyped(mRS, + b.create(), + Allocation.USAGE_SCRIPT | + Allocation.USAGE_GRAPHICS_TEXTURE); + mScript.set_gReadBackTest(mReadBackTest); + + b = new Type.Builder(mRS, + Element.createPixel(mRS, DataType.UNSIGNED_16, + DataKind.PIXEL_DEPTH)); + b.setX(512).setY(512); + mOffscreenDepth = Allocation.createTyped(mRS, + b.create(), + Allocation.USAGE_GRAPHICS_RENDER_TARGET); + mScript.set_gOffscreenDepth(mOffscreenDepth); + + FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot); + initMeshes(model); + + mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8); + mScript.set_gItalic(mItalic); + + initTextAllocation("R.raw.robot"); + + mRS.bindRootScript(mScript); + } +} + + + diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncView.java b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncView.java new file mode 100644 index 0000000..6a85628 --- /dev/null +++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/FBOSyncView.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.fbotest; + +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScriptGL; + +import android.content.Context; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.ScaleGestureDetector; +import android.util.Log; + +public class FBOSyncView extends RSSurfaceView { + + private RenderScriptGL mRS; + private FBOSyncRS mRender; + + private ScaleGestureDetector mScaleDetector; + + private static final int INVALID_POINTER_ID = -1; + private int mActivePointerId = INVALID_POINTER_ID; + + public FBOSyncView(Context context) { + super(context); + ensureRenderScript(); + mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); + } + + private void ensureRenderScript() { + if (mRS == null) { + RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); + sc.setDepth(16, 24); + mRS = createRenderScriptGL(sc); + mRender = new FBOSyncRS(); + mRender.init(mRS, getResources()); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + ensureRenderScript(); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + mRender.surfaceChanged(); + } + + @Override + protected void onDetachedFromWindow() { + mRender = null; + if (mRS != null) { + mRS = null; + destroyRenderScriptGL(); + } + } + + public void loadA3DFile(String path) { + mRender.loadA3DFile(path); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + mScaleDetector.onTouchEvent(ev); + + boolean ret = false; + float x = ev.getX(); + float y = ev.getY(); + + final int action = ev.getAction(); + + switch (action & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + mRender.onActionDown(x, y); + mActivePointerId = ev.getPointerId(0); + ret = true; + break; + } + case MotionEvent.ACTION_MOVE: { + if (!mScaleDetector.isInProgress()) { + mRender.onActionMove(x, y); + } + mRender.onActionDown(x, y); + ret = true; + break; + } + + case MotionEvent.ACTION_UP: { + mActivePointerId = INVALID_POINTER_ID; + break; + } + + case MotionEvent.ACTION_CANCEL: { + mActivePointerId = INVALID_POINTER_ID; + break; + } + + case MotionEvent.ACTION_POINTER_UP: { + final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) + >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int pointerId = ev.getPointerId(pointerIndex); + if (pointerId == mActivePointerId) { + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + x = ev.getX(newPointerIndex); + y = ev.getY(newPointerIndex); + mRender.onActionDown(x, y); + mActivePointerId = ev.getPointerId(newPointerIndex); + } + break; + } + } + + return ret; + } + + private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + @Override + public boolean onScale(ScaleGestureDetector detector) { + mRender.onActionScale(detector.getScaleFactor()); + return true; + } + } +} + + diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs new file mode 100644 index 0000000..b77ccb4 --- /dev/null +++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs @@ -0,0 +1,233 @@ +// Copyright (C) 2011 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma version(1) + +#pragma rs java_package_name(com.android.fbotest) + +#include "rs_graphics.rsh" + +rs_program_vertex gPVBackground; +rs_program_fragment gPFBackground; + +rs_allocation gTGrid; + +rs_program_store gPFSBackground; + +rs_font gItalic; +rs_allocation gTextAlloc; + +rs_allocation gOffscreen; +rs_allocation gOffscreenDepth; +rs_allocation gReadBackTest; + +typedef struct MeshInfo { + rs_mesh mMesh; + int mNumIndexSets; + float3 bBoxMin; + float3 bBoxMax; +} MeshInfo_t; + +MeshInfo_t *gMeshes; + +static float3 gLookAt; + +static float gRotateX; +static float gRotateY; +static float gZoom; + +static float gLastX; +static float gLastY; + +void onActionDown(float x, float y) { + gLastX = x; + gLastY = y; +} + +void onActionScale(float scale) { + + gZoom *= 1.0f / scale; + gZoom = max(0.1f, min(gZoom, 500.0f)); +} + +void onActionMove(float x, float y) { + float dx = gLastX - x; + float dy = gLastY - y; + + if (fabs(dy) <= 2.0f) { + dy = 0.0f; + } + if (fabs(dx) <= 2.0f) { + dx = 0.0f; + } + + gRotateY -= dx; + if (gRotateY > 360) { + gRotateY -= 360; + } + if (gRotateY < 0) { + gRotateY += 360; + } + + gRotateX -= dy; + gRotateX = min(gRotateX, 80.0f); + gRotateX = max(gRotateX, -80.0f); + + gLastX = x; + gLastY = y; +} + +void init() { + gRotateX = 0.0f; + gRotateY = 0.0f; + gZoom = 50.0f; + gLookAt = 0.0f; +} + +void updateMeshInfo() { + rs_allocation allMeshes = rsGetAllocation(gMeshes); + int size = rsAllocationGetDimX(allMeshes); + gLookAt = 0.0f; + float minX, minY, minZ, maxX, maxY, maxZ; + for (int i = 0; i < size; i++) { + MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i); + rsgMeshComputeBoundingBox(info->mMesh, + &minX, &minY, &minZ, + &maxX, &maxY, &maxZ); + info->bBoxMin = (minX, minY, minZ); + info->bBoxMax = (maxX, maxY, maxZ); + gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f; + } + gLookAt = gLookAt / (float)size; +} + +static void renderAllMeshes() { + rs_allocation allMeshes = rsGetAllocation(gMeshes); + int size = rsAllocationGetDimX(allMeshes); + gLookAt = 0.0f; + float minX, minY, minZ, maxX, maxY, maxZ; + for (int i = 0; i < size; i++) { + MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i); + rsgDrawMesh(info->mMesh); + } +} + +static void drawDescription() { + uint width = rsgGetWidth(); + uint height = rsgGetHeight(); + int left = 0, right = 0, top = 0, bottom = 0; + + rsgBindFont(gItalic); + + rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom); + rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom); +} + +static void renderOffscreen(bool useDepth) { + + rsgBindColorTarget(gOffscreen, 0); + if (useDepth) { + rsgBindDepthTarget(gOffscreenDepth); + rsgClearDepth(1.0f); + } else { + rsgClearDepthTarget(); + } + rsgClearColor(0.8f, 0.0f, 0.0f, 1.0f); + + rsgBindProgramVertex(gPVBackground); + rs_matrix4x4 proj; + float aspect = (float)rsAllocationGetDimX(gOffscreen) / (float)rsAllocationGetDimY(gOffscreen); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPFSBackground); + rsgBindTexture(gPFBackground, 0, gTGrid); + + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + // Position our models on the screen + rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom); + rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + + renderAllMeshes(); + + // Render into the frambuffer + rsgClearAllRenderTargets(); +} + +static void drawOffscreenResult(int posX, int posY, rs_allocation texture) { + // display the result + rs_matrix4x4 proj, matrix; + rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500); + rsgProgramVertexLoadProjectionMatrix(&proj); + rsMatrixLoadIdentity(&matrix); + rsgProgramVertexLoadModelMatrix(&matrix); + rsgBindTexture(gPFBackground, 0, texture); + float startX = posX, startY = posY; + float width = 256, height = 256; + rsgDrawQuadTexCoords(startX, startY, 0, 0, 1, + startX, startY + height, 0, 0, 0, + startX + width, startY + height, 0, 1, 0, + startX + width, startY, 0, 1, 1); +} + +int root(void) { + + rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); + rsgClearDepth(1.0f); + + renderOffscreen(true); + drawOffscreenResult(0, 0, gOffscreen); + + + uint32_t w = rsAllocationGetDimX(gOffscreen); + uint32_t h = rsAllocationGetDimY(gOffscreen); + uint32_t numElements = w*h; + + rsgAllocationSyncAll(gOffscreen, RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET); + + rsAllocationCopy2DRange(gReadBackTest, 0, 0, 0, + RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, w, h, + gOffscreen, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X); + + rsgAllocationSyncAll(gReadBackTest); + drawOffscreenResult(0, 300, gReadBackTest); + + rsgBindProgramVertex(gPVBackground); + rs_matrix4x4 proj; + float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); + rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f); + rsgProgramVertexLoadProjectionMatrix(&proj); + + rsgBindProgramFragment(gPFBackground); + rsgBindProgramStore(gPFSBackground); + rsgBindTexture(gPFBackground, 0, gTGrid); + + rs_matrix4x4 matrix; + rsMatrixLoadIdentity(&matrix); + // Position our models on the screen + rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom); + rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f); + rsgProgramVertexLoadModelMatrix(&matrix); + + renderAllMeshes(); + + drawDescription(); + + return 0; +} diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/flares.png b/tests/RenderScriptTests/PerfTest/res/drawable/flares.png Binary files differnew file mode 100644 index 0000000..3a5c970 --- /dev/null +++ b/tests/RenderScriptTests/PerfTest/res/drawable/flares.png diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/light1.jpg b/tests/RenderScriptTests/PerfTest/res/drawable/light1.jpg Binary files differnew file mode 100644 index 0000000..2f2f10e --- /dev/null +++ b/tests/RenderScriptTests/PerfTest/res/drawable/light1.jpg diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/space.jpg b/tests/RenderScriptTests/PerfTest/res/drawable/space.jpg Binary files differnew file mode 100644 index 0000000..b61f6a3 --- /dev/null +++ b/tests/RenderScriptTests/PerfTest/res/drawable/space.jpg diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java index 5ca49ad..3f57799 100644 --- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java +++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java @@ -38,6 +38,10 @@ import android.renderscript.ProgramStore.BlendSrcFunc; import android.renderscript.ProgramStore.BlendDstFunc; import android.renderscript.RenderScript.RSMessageHandler; import android.renderscript.Sampler.Value; +import android.renderscript.Mesh.Primitive; +import android.renderscript.Matrix4f; +import android.renderscript.ProgramVertexFixedFunction; + import android.util.Log; @@ -47,7 +51,7 @@ public class RsBenchRS { private static final String SAMPLE_TEXT = "Bench Test"; private static final String LIST_TEXT = "This is a sample list of text to show in the list view"; - + private static int PARTICLES_COUNT = 12000; int mWidth; int mHeight; int mLoops; @@ -84,6 +88,7 @@ public class RsBenchRS { private Sampler mLinearWrap; private Sampler mMipLinearWrap; private Sampler mNearestClamp; + private Sampler mNearesWrap; private ProgramStore mProgStoreBlendNoneDepth; private ProgramStore mProgStoreBlendNone; @@ -108,6 +113,7 @@ public class RsBenchRS { private ScriptField_VertexShaderConstants3_s mVSConstPixel; private ScriptField_FragentShaderConstants3_s mFSConstPixel; + private ProgramRaster mCullBack; private ProgramRaster mCullFront; private ProgramRaster mCullNone; @@ -123,6 +129,7 @@ public class RsBenchRS { private Mesh mWbyHMesh; private Mesh mTorus; private Mesh mSingleMesh; + private Mesh mParticlesMesh; Font mFontSans; Font mFontSerif; @@ -131,6 +138,8 @@ public class RsBenchRS { private ScriptField_ListAllocs_s mTextureAllocs; private ScriptField_ListAllocs_s mSampleTextAllocs; private ScriptField_ListAllocs_s mSampleListViewAllocs; + private ScriptField_VpConsts mPvStarAlloc; + private ScriptC_rsbench mScript; @@ -303,6 +312,15 @@ public class RsBenchRS { mScript.set_gProgStoreBlendNone(mProgStoreBlendNone); mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha); mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd); + + // For GALAXY + builder = new ProgramStore.Builder(mRS); + builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO); + mRS.bindProgramStore(builder.create()); + + builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE); + mScript.set_gPSLights(builder.create()); + } private void initProgramFragment() { @@ -319,8 +337,59 @@ public class RsBenchRS { mScript.set_gProgFragmentColor(mProgFragmentColor); mScript.set_gProgFragmentTexture(mProgFragmentTexture); + + + // For Galaxy live wallpaper drawing + ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS); + builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, + ProgramFragmentFixedFunction.Builder.Format.RGB, 0); + ProgramFragment pfb = builder.create(); + pfb.bindSampler(mNearesWrap, 0); + mScript.set_gPFBackground(pfb); + + builder = new ProgramFragmentFixedFunction.Builder(mRS); + builder.setPointSpriteTexCoordinateReplacement(true); + builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE, + ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); + builder.setVaryingColor(true); + ProgramFragment pfs = builder.create(); + pfs.bindSampler(mMipLinearWrap, 0); + mScript.set_gPFStars(pfs); + } + private Matrix4f getProjectionNormalized(int w, int h) { + // range -1,1 in the narrow axis at z = 0. + Matrix4f m1 = new Matrix4f(); + Matrix4f m2 = new Matrix4f(); + + if(w > h) { + float aspect = ((float)w) / h; + m1.loadFrustum(-aspect,aspect, -1,1, 1,100); + } else { + float aspect = ((float)h) / w; + m1.loadFrustum(-1,1, -aspect,aspect, 1,100); + } + + m2.loadRotate(180, 0, 1, 0); + m1.loadMultiply(m1, m2); + + m2.loadScale(-2, 2, 1); + m1.loadMultiply(m1, m2); + + m2.loadTranslate(0, 0, 2); + m1.loadMultiply(m1, m2); + return m1; + } + + private void updateProjectionMatrices() { + Matrix4f projNorm = getProjectionNormalized(mBenchmarkDimX, mBenchmarkDimY); + ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item(); + i.Proj = projNorm; + i.MVP = projNorm; + mPvStarAlloc.set(i, 0, true); + } + private void initProgramVertex() { ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); mProgVertex = pvb.create(); @@ -332,6 +401,39 @@ public class RsBenchRS { mPVA.setProjection(proj); mScript.set_gProgVertex(mProgVertex); + + // For galaxy live wallpaper + mPvStarAlloc = new ScriptField_VpConsts(mRS, 1); + mScript.bind_vpConstants(mPvStarAlloc); + updateProjectionMatrices(); + + ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS); + String t = "varying vec4 varColor;\n" + + "varying vec2 varTex0;\n" + + "void main() {\n" + + " float dist = ATTRIB_position.y;\n" + + " float angle = ATTRIB_position.x;\n" + + " float x = dist * sin(angle);\n" + + " float y = dist * cos(angle) * 0.892;\n" + + " float p = dist * 5.5;\n" + + " float s = cos(p);\n" + + " float t = sin(p);\n" + + " vec4 pos;\n" + + " pos.x = t * x + s * y;\n" + + " pos.y = s * x - t * y;\n" + + " pos.z = ATTRIB_position.z;\n" + + " pos.w = 1.0;\n" + + " gl_Position = UNI_MVP * pos;\n" + + " gl_PointSize = ATTRIB_color.a * 10.0;\n" + + " varColor.rgb = ATTRIB_color.rgb;\n" + + " varColor.a = 1.0;\n" + + "}\n"; + sb.setShader(t); + sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement()); + sb.addConstant(mPvStarAlloc.getType()); + ProgramVertex pvs = sb.create(); + pvs.bindConstants(mPvStarAlloc.getAllocation(), 0); + mScript.set_gPVStars(pvs); } private void initCustomShaders() { @@ -429,6 +531,11 @@ public class RsBenchRS { mScript.set_gTexTransparent(mTexTransparent); mScript.set_gTexChecker(mTexChecker); mScript.set_gTexGlobe(mTexGlobe); + + // For Galaxy live wallpaper + mScript.set_gTSpace(loadTextureRGB(R.drawable.space)); + mScript.set_gTLight1(loadTextureRGB(R.drawable.light1)); + mScript.set_gTFlares(loadTextureARGB(R.drawable.flares)); } private void initFonts() { @@ -443,6 +550,19 @@ public class RsBenchRS { mScript.set_gFontSerif(mFontSerif); } + private void createParticlesMesh() { + ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT); + + final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS); + meshBuilder.addVertexAllocation(p.getAllocation()); + final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex(); + meshBuilder.addIndexSetType(Primitive.POINT); + mParticlesMesh = meshBuilder.create(); + + mScript.set_gParticlesMesh(mParticlesMesh); + mScript.bind_Particles(p); + } + private void initMesh() { m10by10Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 10, 10); mScript.set_g10by10Mesh(m10by10Mesh); @@ -461,6 +581,8 @@ public class RsBenchRS { mTorus = (Mesh)entry.getObject(); mScript.set_gTorusMesh(mTorus); } + + createParticlesMesh(); } private void initSamplers() { @@ -474,6 +596,7 @@ public class RsBenchRS { mLinearClamp = Sampler.CLAMP_LINEAR(mRS); mNearestClamp = Sampler.CLAMP_NEAREST(mRS); mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS); + mNearesWrap = Sampler.WRAP_NEAREST(mRS); mScript.set_gLinearClamp(mLinearClamp); mScript.set_gLinearWrap(mLinearWrap); @@ -527,10 +650,10 @@ public class RsBenchRS { initSamplers(); initProgramStore(); initProgramFragment(); + initMesh(); initProgramVertex(); initFonts(); loadImages(); - initMesh(); initProgramRaster(); initCustomShaders(); diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs index 89c5e5a..6d80b0e 100644 --- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs +++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs @@ -23,9 +23,50 @@ const int RS_MSG_TEST_DONE = 100; const int RS_MSG_RESULTS_READY = 101; -const int gMaxModes = 30; +const int gMaxModes = 31; int gMaxLoops; +// Parameters for galaxy live wallpaper +rs_allocation gTSpace; +rs_allocation gTLight1; +rs_allocation gTFlares; +rs_mesh gParticlesMesh; + +rs_program_fragment gPFBackground; +rs_program_fragment gPFStars; +rs_program_vertex gPVStars; +rs_program_vertex gPVBkProj; +rs_program_store gPSLights; + +float gXOffset = 0.5f; + +#define ELLIPSE_RATIO 0.892f +#define PI 3.1415f +#define TWO_PI 6.283f +#define ELLIPSE_TWIST 0.023333333f + +static float angle = 50.f; +static int gOldWidth; +static int gOldHeight; +static int gWidth; +static int gHeight; +static float gSpeed[12000]; +static int gGalaxyRadius = 300; +static rs_allocation gParticlesBuffer; + +typedef struct __attribute__((packed, aligned(4))) Particle { + uchar4 color; + float3 position; +} Particle_t; +Particle_t *Particles; + +typedef struct VpConsts { + rs_matrix4x4 Proj; + rs_matrix4x4 MVP; +} VpConsts_t; +VpConsts_t *vpConstants; +// End of parameters for galaxy live wallpaper + // Allocation to send test names back to java char *gStringBuffer = 0; // Allocation to write the results into @@ -110,6 +151,141 @@ static float textColors[] = {1.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.6f, 0.7f, 1.0f, }; +/** + * Methods to draw the galaxy live wall paper + */ +static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) { + return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart)); +} + +/** + * Helper function to generate the stars. + */ +static float randomGauss() { + float x1; + float x2; + float w = 2.f; + + while (w >= 1.0f) { + x1 = rsRand(2.0f) - 1.0f; + x2 = rsRand(2.0f) - 1.0f; + w = x1 * x1 + x2 * x2; + } + + w = sqrt(-2.0f * log(w) / w); + return x1 * w; +} + +/** + * Generates the properties for a given star. + */ +static void createParticle(Particle_t *part, int idx, float scale) { + float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f); + float id = d / gGalaxyRadius; + float z = randomGauss() * 0.4f * (1.0f - id); + float p = -d * ELLIPSE_TWIST; + + if (d < gGalaxyRadius * 0.33f) { + part->color.x = (uchar) (220 + id * 35); + part->color.y = 220; + part->color.z = 220; + } else { + part->color.x = 180; + part->color.y = 180; + part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f); + } + // Stash point size * 10 in Alpha + part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60); + + if (d > gGalaxyRadius * 0.15f) { + z *= 0.6f * (1.0f - id); + } else { + z *= 0.72f; + } + + // Map to the projection coordinates (viewport.x = -1.0 -> 1.0) + d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d); + + part->position.x = rsRand(TWO_PI); + part->position.y = d; + gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f; + + part->position.z = z / 5.0f; +} + +/** + * Initialize all the starts, called from Java + */ +void initParticles() { + Particle_t *part = Particles; + float scale = gGalaxyRadius / (gWidth * 0.5f); + int count = rsAllocationGetDimX(gParticlesBuffer); + for (int i = 0; i < count; i ++) { + createParticle(part, i, scale); + part++; + } +} + +static void drawSpace() { + rsgBindProgramFragment(gPFBackground); + rsgBindTexture(gPFBackground, 0, gTSpace); + rsgDrawQuadTexCoords( + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + gWidth, 0.0f, 0.0f, 2.0f, 1.0f, + gWidth, gHeight, 0.0f, 2.0f, 0.0f, + 0.0f, gHeight, 0.0f, 0.0f, 0.0f); +} + +static void drawLights() { + rsgBindProgramVertex(gPVBkProj); + rsgBindProgramFragment(gPFBackground); + rsgBindTexture(gPFBackground, 0, gTLight1); + + float scale = 512.0f / gWidth; + float x = -scale - scale * 0.05f; + float y = -scale; + + scale *= 2.0f; + + rsgDrawQuad(x, y, 0.0f, + x + scale * 1.1f, y, 0.0f, + x + scale * 1.1f, y + scale, 0.0f, + x, y + scale, 0.0f); +} + +static void drawParticles(float offset) { + float a = offset * angle; + float absoluteAngle = fabs(a); + + rs_matrix4x4 matrix; + rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f); + if (gHeight > gWidth) { + rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f); + } else { + rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f); + } + rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f); + rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f); + rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj); + rsMatrixMultiply(&vpConstants->MVP, &matrix); + rsgAllocationSyncAll(rsGetAllocation(vpConstants)); + + rsgBindProgramVertex(gPVStars); + rsgBindProgramFragment(gPFStars); + rsgBindProgramStore(gPSLights); + rsgBindTexture(gPFStars, 0, gTFlares); + + Particle_t *vtx = Particles; + int count = rsAllocationGetDimX(gParticlesBuffer); + for (int i = 0; i < count; i++) { + vtx->position.x = vtx->position.x + gSpeed[i]; + vtx++; + } + + rsgDrawMesh(gParticlesMesh); +} +/* end of methods for drawing galaxy */ + static void setupOffscreenTarget() { rsgBindColorTarget(gRenderBufferColor, 0); rsgBindDepthTarget(gRenderBufferDepth); @@ -333,6 +509,42 @@ static void displayListView() { } } +static void drawGalaxy() { + rsgClearColor(0.f, 0.f, 0.f, 1.f); + gParticlesBuffer = rsGetAllocation(Particles); + rsgBindProgramFragment(gPFBackground); + + gWidth = rsgGetWidth(); + gHeight = rsgGetHeight(); + if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) { + initParticles(); + gOldWidth = gWidth; + gOldHeight = gHeight; + } + + float offset = mix(-1.0f, 1.0f, gXOffset); + drawSpace(); + drawParticles(offset); + drawLights(); +} + +// Display images and text with live wallpaper in the background +static void dispalyLiveWallPaper(int wResolution, int hResolution) { + bindProgramVertexOrtho(); + + drawGalaxy(); + + rsgBindProgramStore(gProgStoreBlendAlpha); + rsgBindProgramFragment(gProgFragmentTexture); + rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); + + drawMeshInPage(0, 0, wResolution, hResolution); + drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution); + drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution); + drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution); + drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution); +} + static float gTorusRotation = 0; static void updateModelMatrix(rs_matrix4x4 *matrix, void *buffer) { if (buffer == 0) { @@ -637,6 +849,7 @@ static const char *testNames[] = { "UI test with image and text display 3 pages", "UI test with image and text display 5 pages", "UI test with list view", + "UI test with live wallpaper", }; void getTestName(int testIndex) { @@ -744,6 +957,9 @@ static void runTest(int index) { case 29: displayListView(); break; + case 30: + dispalyLiveWallPaper(7, 5); + break; } } @@ -767,7 +983,6 @@ static void drawOffscreenResult(int posX, int posY, int width, int height) { } int root(void) { - gRenderSurfaceW = rsgGetWidth(); gRenderSurfaceH = rsgGetHeight(); rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f); diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 223b1fa..7852197 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -291,6 +291,27 @@ static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, return value.data; } +static int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree, + uint32_t attrRes, String8* outError, int32_t defValue = -1) +{ + ssize_t idx = indexOfAttribute(tree, attrRes); + if (idx < 0) { + return defValue; + } + Res_value value; + if (tree.getAttributeValue(idx, &value) != NO_ERROR) { + if (value.dataType == Res_value::TYPE_REFERENCE) { + resTable->resolveReference(&value, 0); + } + if (value.dataType < Res_value::TYPE_FIRST_INT + || value.dataType > Res_value::TYPE_LAST_INT) { + if (outError != NULL) *outError = "attribute is not an integer value"; + return defValue; + } + } + return value.data; +} + static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree, uint32_t attrRes, String8* outError) { @@ -320,11 +341,12 @@ static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& // These are attribute resource constants for the platform, as found // in android.R.attr enum { + LABEL_ATTR = 0x01010001, + ICON_ATTR = 0x01010002, NAME_ATTR = 0x01010003, VERSION_CODE_ATTR = 0x0101021b, VERSION_NAME_ATTR = 0x0101021c, - LABEL_ATTR = 0x01010001, - ICON_ATTR = 0x01010002, + SCREEN_ORIENTATION_ATTR = 0x0101001e, MIN_SDK_VERSION_ATTR = 0x0101020c, MAX_SDK_VERSION_ATTR = 0x01010271, REQ_TOUCH_SCREEN_ATTR = 0x01010227, @@ -634,6 +656,8 @@ int doDump(Bundle* bundle) bool reqDistinctMultitouchFeature = false; bool specScreenPortraitFeature = false; bool specScreenLandscapeFeature = false; + bool reqScreenPortraitFeature = false; + bool reqScreenLandscapeFeature = false; // 2.2 also added some other features that apps can request, but that // have no corresponding permission, so we cannot implement any // back-compatibility heuristic for them. The below are thus unnecessary @@ -1022,6 +1046,18 @@ int doDump(Bundle* bundle) fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string()); goto bail; } + + int32_t orien = getResolvedIntegerAttribute(&res, tree, + SCREEN_ORIENTATION_ATTR, &error); + if (error == "") { + if (orien == 0 || orien == 6 || orien == 8) { + // Requests landscape, sensorLandscape, or reverseLandscape. + reqScreenLandscapeFeature = true; + } else if (orien == 1 || orien == 7 || orien == 9) { + // Requests portrait, sensorPortrait, or reversePortrait. + reqScreenPortraitFeature = true; + } + } } else if (tag == "uses-library") { String8 libraryName = getAttribute(tree, NAME_ATTR, &error); if (error != "") { @@ -1182,12 +1218,16 @@ int doDump(Bundle* bundle) } // Landscape/portrait-related compatibility logic - if (!specScreenLandscapeFeature && !specScreenPortraitFeature && (targetSdk < 13)) { - // If app has not specified whether it requires portrait or landscape - // and is targeting an API before Honeycomb MR2, then assume it requires - // both. - printf("uses-feature:'android.hardware.screen.portrait'\n"); - printf("uses-feature:'android.hardware.screen.landscape'\n"); + if (!specScreenLandscapeFeature && !specScreenPortraitFeature) { + // If the app has specified any activities in its manifest + // that request a specific orientation, then assume that + // orientation is required. + if (reqScreenLandscapeFeature) { + printf("uses-feature:'android.hardware.screen.landscape'\n"); + } + if (reqScreenPortraitFeature) { + printf("uses-feature:'android.hardware.screen.portrait'\n"); + } } if (hasMainActivity) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 7380fc1..47fa68e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -25,11 +25,11 @@ import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.StyleResourceValue; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.impl.ParserFactory; import com.android.layoutlib.bridge.impl.Stack; import com.android.resources.ResourceType; import com.android.util.Pair; -import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -206,6 +206,9 @@ public final class BridgeContext extends Activity { * @param parser the parser to add. */ public void pushParser(BridgeXmlBlockParser parser) { + if (ParserFactory.LOG_PARSER) { + System.out.println("PUSH " + parser.getParser().toString()); + } mParserStack.push(parser); } @@ -213,7 +216,10 @@ public final class BridgeContext extends Activity { * Removes the parser at the top of the stack */ public void popParser() { - mParserStack.pop(); + BridgeXmlBlockParser parser = mParserStack.pop(); + if (ParserFactory.LOG_PARSER) { + System.out.println("POPD " + parser.getParser().toString()); + } } /** @@ -346,9 +352,7 @@ public final class BridgeContext extends Activity { // we need to create a pull parser around the layout XML file, and then // give that to our XmlBlockParser try { - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(xml), "UTF-8"); //$NON-NLS-1$); + XmlPullParser parser = ParserFactory.create(xml); // set the resource ref to have correct view cookies mBridgeInflater.setResourceReference(resource); @@ -687,25 +691,25 @@ public final class BridgeContext extends Activity { */ private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs) throws Resources.NotFoundException { - AtomicBoolean frameworkAttributes = new AtomicBoolean(); - AtomicReference<String> attrName = new AtomicReference<String>(); - TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, frameworkAttributes, attrName); BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length, - style.isFramework(), frameworkAttributes.get(), attrName.get()); - - // loop through all the values in the style map, and init the TypedArray with - // the style we got from the dynamic id - for (Entry<Integer, String> styleAttribute : styleNameMap.entrySet()) { - int index = styleAttribute.getKey().intValue(); + false, true, null); - String name = styleAttribute.getValue(); + // for each attribute, get its name so that we can search it in the style + for (int i = 0 ; i < attrs.length ; i++) { + Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]); + if (resolvedResource != null) { + String attrName = resolvedResource.getSecond(); + // look for the value in the given style + ResourceValue resValue = mRenderResources.findItemInStyle(style, attrName); - // get the value from the style, or its parent styles. - ResourceValue resValue = mRenderResources.findItemInStyle(style, name); + if (resValue != null) { + // resolve it to make sure there are no references left. + ta.bridgeSetValue(i, attrName, mRenderResources.resolveResValue(resValue)); - // resolve it to make sure there are no references left. - ta.bridgeSetValue(index, name, mRenderResources.resolveResValue(resValue)); + resValue = mRenderResources.resolveResValue(resValue); + } + } } ta.sealArray(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java index 7c90a31..4a6393d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java @@ -22,10 +22,10 @@ import com.android.ide.common.rendering.api.MergeCookie; import com.android.ide.common.rendering.api.ResourceReference; import com.android.ide.common.rendering.api.ResourceValue; import com.android.layoutlib.bridge.Bridge; +import com.android.layoutlib.bridge.impl.ParserFactory; import com.android.resources.ResourceType; import com.android.util.Pair; -import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import android.content.Context; @@ -36,7 +36,6 @@ import android.view.View; import android.view.ViewGroup; import java.io.File; -import java.io.FileInputStream; /** * Custom implementation of {@link LayoutInflater} to handle custom views. @@ -175,9 +174,7 @@ public final class BridgeInflater extends LayoutInflater { File f = new File(value.getValue()); if (f.isFile()) { try { - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$ + XmlPullParser parser = ParserFactory.create(f); BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( parser, bridgeContext, false); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java index d0b90fb..1756496 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java @@ -21,12 +21,12 @@ import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.ResourceValue; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.impl.ParserFactory; import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.ninepatch.NinePatch; import com.android.resources.ResourceType; import com.android.util.Pair; -import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -131,14 +131,16 @@ public final class BridgeResources extends Resources { platformStyleable, styleableName); } - private ResourceValue getResourceValue(int id, boolean[] platformResFlag_out) { + private Pair<String, ResourceValue> getResourceValue(int id, boolean[] platformResFlag_out) { // first get the String related to this id in the framework Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id); if (resourceInfo != null) { platformResFlag_out[0] = true; - return mContext.getRenderResources().getFrameworkResource( - resourceInfo.getFirst(), resourceInfo.getSecond()); + String attributeName = resourceInfo.getSecond(); + + return Pair.of(attributeName, mContext.getRenderResources().getFrameworkResource( + resourceInfo.getFirst(), attributeName)); } // didn't find a match in the framework? look in the project. @@ -147,8 +149,10 @@ public final class BridgeResources extends Resources { if (resourceInfo != null) { platformResFlag_out[0] = false; - return mContext.getRenderResources().getProjectResource( - resourceInfo.getFirst(), resourceInfo.getSecond()); + String attributeName = resourceInfo.getSecond(); + + return Pair.of(attributeName, mContext.getRenderResources().getProjectResource( + resourceInfo.getFirst(), attributeName)); } } @@ -157,10 +161,10 @@ public final class BridgeResources extends Resources { @Override public Drawable getDrawable(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - return ResourceHelper.getDrawable(value, mContext); + return ResourceHelper.getDrawable(value.getSecond(), mContext); } // id was not found or not resolved. Throw a NotFoundException. @@ -172,11 +176,11 @@ public final class BridgeResources extends Resources { @Override public int getColor(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { try { - return ResourceHelper.getColor(value.getValue()); + return ResourceHelper.getColor(value.getSecond().getValue()); } catch (NumberFormatException e) { Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/); @@ -193,10 +197,11 @@ public final class BridgeResources extends Resources { @Override public ColorStateList getColorStateList(int id) throws NotFoundException { - ResourceValue resValue = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> resValue = getResourceValue(id, mPlatformResourceFlag); if (resValue != null) { - ColorStateList stateList = ResourceHelper.getColorStateList(resValue, mContext); + ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(), + mContext); if (stateList != null) { return stateList; } @@ -211,10 +216,10 @@ public final class BridgeResources extends Resources { @Override public CharSequence getText(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - return value.getValue(); + return value.getSecond().getValue(); } // id was not found or not resolved. Throw a NotFoundException. @@ -226,9 +231,10 @@ public final class BridgeResources extends Resources { @Override public XmlResourceParser getLayout(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag); - if (value != null) { + if (v != null) { + ResourceValue value = v.getSecond(); XmlPullParser parser = null; try { @@ -243,9 +249,7 @@ public final class BridgeResources extends Resources { if (xml.isFile()) { // we need to create a pull parser around the layout XML file, and then // give that to our XmlBlockParser - parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(xml), "UTF-8"); //$NON-NLS-1$); + parser = ParserFactory.create(xml); } } @@ -271,9 +275,10 @@ public final class BridgeResources extends Resources { @Override public XmlResourceParser getAnimation(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag); - if (value != null) { + if (v != null) { + ResourceValue value = v.getSecond(); XmlPullParser parser = null; try { @@ -281,9 +286,7 @@ public final class BridgeResources extends Resources { if (xml.isFile()) { // we need to create a pull parser around the layout XML file, and then // give that to our XmlBlockParser - parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(xml), "UTF-8"); //$NON-NLS-1$); + parser = ParserFactory.create(xml); return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } @@ -317,10 +320,10 @@ public final class BridgeResources extends Resources { @Override public float getDimension(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getValue(); + String v = value.getSecond().getValue(); if (v != null) { if (v.equals(BridgeConstants.MATCH_PARENT) || @@ -330,7 +333,8 @@ public final class BridgeResources extends Resources { return LayoutParams.WRAP_CONTENT; } - if (ResourceHelper.stringToFloat(v, mTmpValue) && + if (ResourceHelper.parseFloatAttribute( + value.getFirst(), v, mTmpValue, true /*requireUnit*/) && mTmpValue.type == TypedValue.TYPE_DIMENSION) { return mTmpValue.getDimension(mMetrics); } @@ -346,13 +350,14 @@ public final class BridgeResources extends Resources { @Override public int getDimensionPixelOffset(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getValue(); + String v = value.getSecond().getValue(); if (v != null) { - if (ResourceHelper.stringToFloat(v, mTmpValue) && + if (ResourceHelper.parseFloatAttribute( + value.getFirst(), v, mTmpValue, true /*requireUnit*/) && mTmpValue.type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelOffset(mTmpValue.data, mMetrics); } @@ -368,13 +373,14 @@ public final class BridgeResources extends Resources { @Override public int getDimensionPixelSize(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getValue(); + String v = value.getSecond().getValue(); if (v != null) { - if (ResourceHelper.stringToFloat(v, mTmpValue) && + if (ResourceHelper.parseFloatAttribute( + value.getFirst(), v, mTmpValue, true /*requireUnit*/) && mTmpValue.type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelSize(mTmpValue.data, mMetrics); } @@ -390,10 +396,10 @@ public final class BridgeResources extends Resources { @Override public int getInteger(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - if (value != null && value.getValue() != null) { - String v = value.getValue(); + if (value != null && value.getSecond().getValue() != null) { + String v = value.getSecond().getValue(); int radix = 10; if (v.startsWith("0x")) { v = v.substring(2); @@ -445,10 +451,10 @@ public final class BridgeResources extends Resources { @Override public String getString(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - if (value != null && value.getValue() != null) { - return value.getValue(); + if (value != null && value.getSecond().getValue() != null) { + return value.getSecond().getValue(); } // id was not found or not resolved. Throw a NotFoundException. @@ -461,13 +467,14 @@ public final class BridgeResources extends Resources { @Override public void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getValue(); + String v = value.getSecond().getValue(); if (v != null) { - if (ResourceHelper.stringToFloat(v, outValue)) { + if (ResourceHelper.parseFloatAttribute(value.getFirst(), v, outValue, + false /*requireUnit*/)) { return; } @@ -490,19 +497,17 @@ public final class BridgeResources extends Resources { @Override public XmlResourceParser getXml(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getValue(); + String v = value.getSecond().getValue(); if (v != null) { // check this is a file - File f = new File(value.getValue()); + File f = new File(v); if (f.isFile()) { try { - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$); + XmlPullParser parser = ParserFactory.create(f); return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } catch (XmlPullParserException e) { @@ -535,9 +540,7 @@ public final class BridgeResources extends Resources { File f = new File(file); try { - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$); + XmlPullParser parser = ParserFactory.create(f); return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } catch (XmlPullParserException e) { @@ -554,10 +557,10 @@ public final class BridgeResources extends Resources { @Override public InputStream openRawResource(int id) throws NotFoundException { - ResourceValue value = getResourceValue(id, mPlatformResourceFlag); + Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String path = value.getValue(); + String path = value.getSecond().getValue(); if (path != null) { // check this is a file diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java index b1fbf08..260cdc8 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java @@ -24,10 +24,10 @@ import com.android.ide.common.rendering.api.StyleResourceValue; import com.android.internal.util.XmlUtils; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.impl.ParserFactory; import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.resources.ResourceType; -import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -41,7 +41,6 @@ import android.view.LayoutInflater_Delegate; import android.view.ViewGroup.LayoutParams; import java.io.File; -import java.io.FileInputStream; import java.util.Arrays; import java.util.Map; @@ -211,7 +210,7 @@ public final class BridgeTypedArray extends TypedArray { Map<String, Integer> map = null; if (mPlatformStyleable) { map = Bridge.getEnumValues(mNames[index]); - } else { + } else if (mStyleableName != null) { // get the styleable matching the resolved name RenderResources res = mContext.getRenderResources(); ResourceValue styleable = res.getProjectResource(ResourceType.DECLARE_STYLEABLE, @@ -331,9 +330,7 @@ public final class BridgeTypedArray extends TypedArray { File f = new File(value); if (f.isFile()) { try { - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$); + XmlPullParser parser = ParserFactory.create(f); BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( parser, mContext, resValue.isFramework()); @@ -377,26 +374,7 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public int getInteger(int index, int defValue) { - if (mResourceData[index] == null) { - return defValue; - } - - String s = mResourceData[index].getValue(); - - if (s != null) { - try { - return Integer.parseInt(s); - } catch (NumberFormatException e) { - Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, - String.format( - "\"%s\" in attribute \"%2$s\" cannont be converted to an integer.", - s, mNames[index]), null /*data*/); - - // The default value is returned below. - } - } - - return defValue; + return getInt(index, defValue); } /** @@ -434,7 +412,7 @@ public final class BridgeTypedArray extends TypedArray { return defValue; } - if (ResourceHelper.stringToFloat(s, mValue)) { + if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) { return mValue.getDimension(mBridgeResources.mMetrics); } @@ -561,7 +539,7 @@ public final class BridgeTypedArray extends TypedArray { throw new RuntimeException(); } - if (ResourceHelper.stringToFloat(s, mValue)) { + if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) { float f = mValue.getDimension(mBridgeResources.mMetrics); final int res = (int)(f+0.5f); @@ -599,14 +577,15 @@ public final class BridgeTypedArray extends TypedArray { return defValue; } - if (ResourceHelper.stringToFloat(value, mValue)) { + if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, + false /*requireUnit*/)) { return mValue.getFraction(base, pbase); } // looks like we were unable to resolve the fraction value Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, String.format( - "\"%1$s\" in attribute \"%2$s\" cannont be converted to a fraction.", + "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.", value, mNames[index]), null /*data*/); return defValue; @@ -803,7 +782,8 @@ public final class BridgeTypedArray extends TypedArray { String s = mResourceData[index].getValue(); - return ResourceHelper.stringToFloat(s, outValue); + return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, + false /*requireUnit*/); } /** diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java index 70dbaa4..1016b32 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java @@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.android; import com.android.ide.common.rendering.api.ILayoutPullParser; +import com.android.layoutlib.bridge.impl.ParserFactory; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -54,6 +55,10 @@ public class BridgeXmlBlockParser implements XmlResourceParser { * @param platformFile Indicates whether the the file is a platform file or not. */ public BridgeXmlBlockParser(XmlPullParser parser, BridgeContext context, boolean platformFile) { + if (ParserFactory.LOG_PARSER) { + System.out.println("CRTE " + parser.toString()); + } + mParser = parser; mContext = context; mPlatformFile = platformFile; @@ -65,6 +70,10 @@ public class BridgeXmlBlockParser implements XmlResourceParser { } } + public XmlPullParser getParser() { + return mParser; + } + public boolean isPlatformFile() { return mPlatformFile; } @@ -247,18 +256,63 @@ public class BridgeXmlBlockParser implements XmlResourceParser { public int next() throws XmlPullParserException, IOException { if (!mStarted) { mStarted = true; + + if (ParserFactory.LOG_PARSER) { + System.out.println("STRT " + mParser.toString()); + } + return START_DOCUMENT; } + int ev = mParser.next(); + if (ParserFactory.LOG_PARSER) { + System.out.println("NEXT " + mParser.toString() + " " + + eventTypeToString(mEventType) + " -> " + eventTypeToString(ev)); + } + if (ev == END_TAG && mParser.getDepth() == 1) { // done with parser remove it from the context stack. ensurePopped(); + + if (ParserFactory.LOG_PARSER) { + System.out.println(""); + } } + mEventType = ev; return ev; } + public static String eventTypeToString(int eventType) { + switch (eventType) { + case START_DOCUMENT: + return "START_DOC"; + case END_DOCUMENT: + return "END_DOC"; + case START_TAG: + return "START_TAG"; + case END_TAG: + return "END_TAG"; + case TEXT: + return "TEXT"; + case CDSECT: + return "CDSECT"; + case ENTITY_REF: + return "ENTITY_REF"; + case IGNORABLE_WHITESPACE: + return "IGNORABLE_WHITESPACE"; + case PROCESSING_INSTRUCTION: + return "PROCESSING_INSTRUCTION"; + case COMMENT: + return "COMMENT"; + case DOCDECL: + return "DOCDECL"; + } + + return "????"; + } + public void require(int type, String namespace, String name) throws XmlPullParserException { if (type != getEventType() diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index 060e6ee..df701d5 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -22,11 +22,11 @@ import com.android.ide.common.rendering.api.StyleResourceValue; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; +import com.android.layoutlib.bridge.impl.ParserFactory; import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.resources.Density; import com.android.resources.ResourceType; -import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -60,7 +60,7 @@ abstract class CustomBar extends LinearLayout { protected abstract TextView getStyleableTextView(); - protected CustomBar(Context context, Density density, String layoutPath) + protected CustomBar(Context context, Density density, String layoutPath, String name) throws XmlPullParserException { super(context); setOrientation(LinearLayout.HORIZONTAL); @@ -69,11 +69,8 @@ abstract class CustomBar extends LinearLayout { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput( - getClass().getResourceAsStream(layoutPath), - "UTF8"); //$NON-NLS-1$ + XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), + name); BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( parser, (BridgeContext) context, false /*platformFile*/); @@ -230,7 +227,8 @@ abstract class CustomBar extends LinearLayout { if (textSize != null) { TypedValue out = new TypedValue(); - if (ResourceHelper.stringToFloat(textSize.getValue(), out)) { + if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out, + true /*requireUnit*/)) { textView.setTextSize( out.getDimension(bridgeContext.getResources().mMetrics)); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java index 3af4e3a..f6edea4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java @@ -29,7 +29,7 @@ public class FakeActionBar extends CustomBar { public FakeActionBar(Context context, Density density, String label, String icon) throws XmlPullParserException { - super(context, density, "/bars/action_bar.xml"); + super(context, density, "/bars/action_bar.xml", "action_bar.xml"); // Cannot access the inside items through id because no R.id values have been // created for them. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java index 9fab51a..5569e06 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java @@ -30,7 +30,7 @@ import android.widget.TextView; public class PhoneSystemBar extends CustomBar { public PhoneSystemBar(Context context, Density density) throws XmlPullParserException { - super(context, density, "/bars/phone_system_bar.xml"); + super(context, density, "/bars/phone_system_bar.xml", "phone_system_bar.xml"); setGravity(mGravity | Gravity.RIGHT); setBackgroundColor(0xFF000000); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java index 5ca68fa..456ddb4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java @@ -29,7 +29,7 @@ import android.widget.TextView; public class TabletSystemBar extends CustomBar { public TabletSystemBar(Context context, Density density) throws XmlPullParserException { - super(context, density, "/bars/tablet_system_bar.xml"); + super(context, density, "/bars/tablet_system_bar.xml", "tablet_system_bar.xml"); setBackgroundColor(0xFF000000); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java index d7401d9..5f5ebc4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java @@ -29,7 +29,7 @@ public class TitleBar extends CustomBar { public TitleBar(Context context, Density density, String label) throws XmlPullParserException { - super(context, density, "/bars/title_bar.xml"); + super(context, density, "/bars/title_bar.xml", "title_bar.xml"); // Cannot access the inside items through id because no R.id values have been // created for them. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java new file mode 100644 index 0000000..a235ec3 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.layoutlib.bridge.impl; + + +import org.kxml2.io.KXmlParser; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +/** + * A factory for {@link XmlPullParser}. + * + */ +public class ParserFactory { + + private final static String ENCODING = "UTF-8"; //$NON-NLS-1$ + + public final static boolean LOG_PARSER = false; + + public static XmlPullParser create(File f) + throws XmlPullParserException, FileNotFoundException { + KXmlParser parser = instantiateParser(f.getName()); + parser.setInput(new FileInputStream(f), ENCODING); + return parser; + } + + public static XmlPullParser create(InputStream stream, String name) + throws XmlPullParserException { + KXmlParser parser = instantiateParser(name); + parser.setInput(stream, ENCODING); + return parser; + } + + private static KXmlParser instantiateParser(String name) throws XmlPullParserException { + KXmlParser parser; + if (name != null) { + parser = new CustomParser(name); + } else { + parser = new KXmlParser(); + } + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + return parser; + } + + private static class CustomParser extends KXmlParser { + private final String mName; + + CustomParser(String name) { + super(); + mName = name; + } + + @Override + public String toString() { + return mName; + } + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index b800519..aa30e29 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -984,7 +984,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { "status_bar_height"); if (value != null) { - TypedValue typedValue = ResourceHelper.getValue(value.getValue()); + TypedValue typedValue = ResourceHelper.getValue("status_bar_height", + value.getValue(), true /*requireUnit*/); if (typedValue != null) { // compute the pixel value based on the display metrics mStatusBarSize = (int)typedValue.getDimension(metrics); @@ -1016,7 +1017,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { if (value != null) { // get the numerical value, if available - TypedValue typedValue = ResourceHelper.getValue(value.getValue()); + TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(), + true /*requireUnit*/); if (typedValue != null) { // compute the pixel value based on the display metrics mActionBarSize = (int)typedValue.getDimension(metrics); @@ -1040,7 +1042,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { if (value != null) { // get the numerical value, if available - TypedValue typedValue = ResourceHelper.getValue(value.getValue()); + TypedValue typedValue = ResourceHelper.getValue("windowTitleSize", + value.getValue(), true /*requireUnit*/); if (typedValue != null) { // compute the pixel value based on the display metrics mTitleBarSize = (int)typedValue.getDimension(metrics); @@ -1062,7 +1065,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { "status_bar_height"); if (value != null) { - TypedValue typedValue = ResourceHelper.getValue(value.getValue()); + TypedValue typedValue = ResourceHelper.getValue("status_bar_height", + value.getValue(), true /*requireUnit*/); if (typedValue != null) { // compute the pixel value based on the display metrics mSystemBarSize = (int)typedValue.getDimension(metrics); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java index e5efa4e..6dcb693 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java @@ -27,7 +27,6 @@ import com.android.ninepatch.NinePatch; import com.android.ninepatch.NinePatchChunk; import com.android.resources.Density; -import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -121,9 +120,7 @@ public final class ResourceHelper { try { // let the framework inflate the ColorStateList from the XML file, by // providing an XmlPullParser - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$); + XmlPullParser parser = ParserFactory.create(f); BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( parser, context, resValue.isFramework()); @@ -203,9 +200,7 @@ public final class ResourceHelper { if (f.isFile()) { try { // let the framework inflate the Drawable from the XML file. - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$); + XmlPullParser parser = ParserFactory.create(f); BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( parser, context, value.isFramework()); @@ -341,11 +336,11 @@ public final class ResourceHelper { }; /** - * Returns the raw value from the given string. + * Returns the raw value from the given attribute float-type value string. * This object is only valid until the next call on to {@link ResourceHelper}. */ - public static TypedValue getValue(String s) { - if (stringToFloat(s, mValue)) { + public static TypedValue getValue(String attribute, String value, boolean requireUnit) { + if (parseFloatAttribute(attribute, value, mValue, requireUnit)) { return mValue; } @@ -353,22 +348,27 @@ public final class ResourceHelper { } /** - * Convert the string into a {@link TypedValue}. - * @param s - * @param outValue + * Parse a float attribute and return the parsed value into a given TypedValue. + * @param attribute the name of the attribute. Can be null if <var>requireUnit</var> is false. + * @param value the string value of the attribute + * @param outValue the TypedValue to receive the parsed value + * @param requireUnit whether the value is expected to contain a unit. * @return true if success. */ - public static boolean stringToFloat(String s, TypedValue outValue) { + public static boolean parseFloatAttribute(String attribute, String value, + TypedValue outValue, boolean requireUnit) { + assert requireUnit == false || attribute != null; + // remove the space before and after - s = s.trim(); - int len = s.length(); + value = value.trim(); + int len = value.length(); if (len <= 0) { return false; } // check that there's no non ascii characters. - char[] buf = s.toCharArray(); + char[] buf = value.toCharArray(); for (int i = 0 ; i < len ; i++) { if (buf[i] > 255) { return false; @@ -381,7 +381,7 @@ public final class ResourceHelper { } // now look for the string that is after the float... - Matcher m = sFloatPattern.matcher(s); + Matcher m = sFloatPattern.matcher(value); if (m.matches()) { String f_str = m.group(1); String end = m.group(2); @@ -397,45 +397,7 @@ public final class ResourceHelper { if (end.length() > 0 && end.charAt(0) != ' ') { // Might be a unit... if (parseUnit(end, outValue, sFloatOut)) { - - f *= sFloatOut[0]; - boolean neg = f < 0; - if (neg) { - f = -f; - } - long bits = (long)(f*(1<<23)+.5f); - int radix; - int shift; - if ((bits&0x7fffff) == 0) { - // Always use 23p0 if there is no fraction, just to make - // things easier to read. - radix = TypedValue.COMPLEX_RADIX_23p0; - shift = 23; - } else if ((bits&0xffffffffff800000L) == 0) { - // Magnitude is zero -- can fit in 0 bits of precision. - radix = TypedValue.COMPLEX_RADIX_0p23; - shift = 0; - } else if ((bits&0xffffffff80000000L) == 0) { - // Magnitude can fit in 8 bits of precision. - radix = TypedValue.COMPLEX_RADIX_8p15; - shift = 8; - } else if ((bits&0xffffff8000000000L) == 0) { - // Magnitude can fit in 16 bits of precision. - radix = TypedValue.COMPLEX_RADIX_16p7; - shift = 16; - } else { - // Magnitude needs entire range, so no fractional part. - radix = TypedValue.COMPLEX_RADIX_23p0; - shift = 23; - } - int mantissa = (int)( - (bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK); - if (neg) { - mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK; - } - outValue.data |= - (radix<<TypedValue.COMPLEX_RADIX_SHIFT) - | (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT); + computeTypedValue(outValue, f, sFloatOut[0]); return true; } return false; @@ -446,8 +408,20 @@ public final class ResourceHelper { if (end.length() == 0) { if (outValue != null) { - outValue.type = TypedValue.TYPE_FLOAT; - outValue.data = Float.floatToIntBits(f); + if (requireUnit == false) { + outValue.type = TypedValue.TYPE_FLOAT; + outValue.data = Float.floatToIntBits(f); + } else { + // no unit when required? Use dp and out an error. + applyUnit(sUnitNames[1], outValue, sFloatOut); + computeTypedValue(outValue, f, sFloatOut[0]); + + Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, + String.format( + "Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!", + value, attribute), + null); + } return true; } } @@ -456,20 +430,64 @@ public final class ResourceHelper { return false; } + private static void computeTypedValue(TypedValue outValue, float value, float scale) { + value *= scale; + boolean neg = value < 0; + if (neg) { + value = -value; + } + long bits = (long)(value*(1<<23)+.5f); + int radix; + int shift; + if ((bits&0x7fffff) == 0) { + // Always use 23p0 if there is no fraction, just to make + // things easier to read. + radix = TypedValue.COMPLEX_RADIX_23p0; + shift = 23; + } else if ((bits&0xffffffffff800000L) == 0) { + // Magnitude is zero -- can fit in 0 bits of precision. + radix = TypedValue.COMPLEX_RADIX_0p23; + shift = 0; + } else if ((bits&0xffffffff80000000L) == 0) { + // Magnitude can fit in 8 bits of precision. + radix = TypedValue.COMPLEX_RADIX_8p15; + shift = 8; + } else if ((bits&0xffffff8000000000L) == 0) { + // Magnitude can fit in 16 bits of precision. + radix = TypedValue.COMPLEX_RADIX_16p7; + shift = 16; + } else { + // Magnitude needs entire range, so no fractional part. + radix = TypedValue.COMPLEX_RADIX_23p0; + shift = 23; + } + int mantissa = (int)( + (bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK); + if (neg) { + mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK; + } + outValue.data |= + (radix<<TypedValue.COMPLEX_RADIX_SHIFT) + | (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT); + } + private static boolean parseUnit(String str, TypedValue outValue, float[] outScale) { str = str.trim(); for (UnitEntry unit : sUnitNames) { if (unit.name.equals(str)) { - outValue.type = unit.type; - outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT; - outScale[0] = unit.scale; - + applyUnit(unit, outValue, outScale); return true; } } return false; } + + private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) { + outValue.type = unit.type; + outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT; + outScale[0] = unit.scale; + } } diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java index 70d5446..96436fe 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java @@ -16,14 +16,11 @@ package com.android.layoutlib.bridge.android; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; +import com.android.layoutlib.bridge.impl.ParserFactory; -import org.kxml2.io.KXmlParser; import org.w3c.dom.Node; import org.xmlpull.v1.XmlPullParser; -import java.io.InputStream; - import junit.framework.TestCase; public class BridgeXmlBlockParserTest extends TestCase { @@ -39,12 +36,12 @@ public class BridgeXmlBlockParserTest extends TestCase { } public void testXmlBlockParser() throws Exception { - XmlPullParser parser = new KXmlParser(); - parser = new BridgeXmlBlockParser(parser, null, false /* platformResourceFlag */); - InputStream input = this.getClass().getClassLoader().getResourceAsStream( - "com/android/layoutlib/testdata/layout1.xml"); - parser.setInput(input, "UTF-8"); //$NON-NLS-1$ + XmlPullParser parser = ParserFactory.create( + getClass().getResourceAsStream("com/android/layoutlib/testdata/layout1.xml"), + "layout1.xml"); + + parser = new BridgeXmlBlockParser(parser, null, false /* platformResourceFlag */); assertEquals(XmlPullParser.START_DOCUMENT, parser.next()); diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 3df3736..4f5349a 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -1374,7 +1374,7 @@ public class WifiStateMachine extends StateMachine { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo); - intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, mLinkProperties); + intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties (mLinkProperties)); if (bssid != null) intent.putExtra(WifiManager.EXTRA_BSSID, bssid); mContext.sendStickyBroadcast(intent); @@ -1390,7 +1390,7 @@ public class WifiStateMachine extends StateMachine { private void sendLinkConfigurationChangedBroadcast() { Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, mLinkProperties); + intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); mContext.sendBroadcast(intent); } @@ -1454,10 +1454,8 @@ public class WifiStateMachine extends StateMachine { Log.d(TAG, "Reset connections and stopping DHCP"); /* - * Reset connections & stop DHCP + * stop DHCP */ - NetworkUtils.resetConnections(mInterfaceName); - if (mDhcpStateMachine != null) { mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP); mDhcpStateMachine.quit(); @@ -1547,7 +1545,6 @@ public class WifiStateMachine extends StateMachine { if (!linkProperties.equals(mLinkProperties)) { Log.d(TAG, "Link configuration changed for netId: " + mLastNetworkId + " old: " + mLinkProperties + "new: " + linkProperties); - NetworkUtils.resetConnections(mInterfaceName); mLinkProperties = linkProperties; sendLinkConfigurationChangedBroadcast(); } @@ -2820,7 +2817,6 @@ public class WifiStateMachine extends StateMachine { if (mWifiInfo.getNetworkId() == result.getNetworkId()) { if (result.hasIpChanged()) { Log.d(TAG,"Reconfiguring IP on connection"); - NetworkUtils.resetConnections(mInterfaceName); transitionTo(mConnectingState); } if (result.hasProxyChanged()) { |