Merge "MTP: Use correct return type for getSupportedObjectProperties"
diff --git a/api/current.xml b/api/current.xml
index f02ec65..b90ac5f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -20161,17 +20161,6 @@
visibility="public"
>
</method>
-<method name="getGetter"
- return="java.lang.reflect.Method"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
<method name="getPropertyName"
return="java.lang.String"
abstract="false"
@@ -20183,17 +20172,6 @@
visibility="public"
>
</method>
-<method name="getSetter"
- return="java.lang.reflect.Method"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
<method name="ofFloat"
return="android.animation.PropertyValuesHolder"
abstract="false"
@@ -20282,19 +20260,6 @@
<parameter name="values" type="float...">
</parameter>
</method>
-<method name="setGetter"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="getter" type="java.lang.reflect.Method">
-</parameter>
-</method>
<method name="setIntValues"
return="void"
abstract="false"
@@ -20347,19 +20312,6 @@
<parameter name="propertyName" type="java.lang.String">
</parameter>
</method>
-<method name="setSetter"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="setter" type="java.lang.reflect.Method">
-</parameter>
-</method>
</class>
<class name="RGBEvaluator"
extends="java.lang.Object"
@@ -75748,6 +75700,16 @@
visibility="public"
>
</field>
+<field name="inPreferQualityOverSpeed"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="inPreferredConfig"
type="android.graphics.Bitmap.Config"
transient="false"
@@ -184371,6 +184333,19 @@
<parameter name="gmtoff" type="long">
</parameter>
</method>
+<method name="getJulianMondayFromWeeksSinceEpoch"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="week" type="int">
+</parameter>
+</method>
<method name="getWeekNumber"
return="int"
abstract="false"
@@ -184382,6 +184357,21 @@
visibility="public"
>
</method>
+<method name="getWeeksSinceEpochFromJulianDay"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="julianDay" type="int">
+</parameter>
+<parameter name="firstDayOfWeek" type="int">
+</parameter>
+</method>
<method name="isEpoch"
return="boolean"
abstract="false"
@@ -184605,6 +184595,17 @@
visibility="public"
>
</field>
+<field name="MONDAY_BEFORE_JULIAN_EPOCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2440585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="MONTH"
type="int"
transient="false"
@@ -227831,6 +227832,19 @@
visibility="public"
>
</method>
+<method name="removeJavascriptInterface"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceName" type="java.lang.String">
+</parameter>
+</method>
<method name="requestFocusNodeHref"
return="void"
abstract="false"
@@ -234517,7 +234531,7 @@
>
<parameter name="year" type="int">
</parameter>
-<parameter name="monthOfYear" type="int">
+<parameter name="month" type="int">
</parameter>
<parameter name="dayOfMonth" type="int">
</parameter>
@@ -234569,6 +234583,172 @@
</parameter>
</method>
</interface>
+<class name="DayPicker"
+ extends="android.widget.FrameLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="DayPicker"
+ type="android.widget.DayPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getSelectedDay"
+ return="java.util.Calendar"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="goTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+<parameter name="forceScroll" type="boolean">
+</parameter>
+</method>
+<method name="goTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="date" type="java.util.Calendar">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+<parameter name="forceScroll" type="boolean">
+</parameter>
+</method>
+<method name="setOnDateChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.DayPicker.OnSelectedDayChangeListener">
+</parameter>
+</method>
+<method name="setRange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="startRangeDate" type="java.util.Calendar">
+</parameter>
+<parameter name="endRangeDate" type="java.util.Calendar">
+</parameter>
+</method>
+<method name="setSelectedDay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectedDay" type="java.util.Calendar">
+</parameter>
+</method>
+</class>
+<interface name="DayPicker.OnSelectedDayChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSelectedDayChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.DayPicker">
+</parameter>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+</method>
+</interface>
<class name="DialerFilter"
extends="android.widget.RelativeLayout"
abstract="false"
@@ -250407,7 +250587,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index f2b5638..a3d7a6e 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -3,6 +3,7 @@
#include <media/IStreamSource.h>
#include <media/mediaplayer.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
@@ -56,7 +57,7 @@
ssize_t n = read(mFd, mem->pointer(), mem->size());
if (n <= 0) {
- mListener->queueCommand(IStreamListener::EOS);
+ mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
} else {
mListener->queueBuffer(index, n);
}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 61ef8f2..a815b3a 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -838,6 +838,44 @@
}
}
+ void getAuthTokenLabel(final IAccountManagerResponse response,
+ final Account account, final String authTokenType) {
+ if (account == null) throw new IllegalArgumentException("account is null");
+ if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
+
+ checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
+
+ long identityToken = clearCallingIdentity();
+ try {
+ new Session(response, account.type, false,
+ false /* stripAuthTokenFromResult */) {
+ protected String toDebugString(long now) {
+ return super.toDebugString(now) + ", getAuthTokenLabel"
+ + ", " + account
+ + ", authTokenType " + authTokenType;
+ }
+
+ public void run() throws RemoteException {
+ mAuthenticator.getAuthTokenLabel(this, authTokenType);
+ }
+
+ public void onResult(Bundle result) {
+ if (result != null) {
+ String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
+ Bundle bundle = new Bundle();
+ bundle.putString(AccountManager.KEY_AUTH_TOKEN_LABEL, label);
+ super.onResult(bundle);
+ return;
+ } else {
+ super.onResult(result);
+ }
+ }
+ }.bind();
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
public void getAuthToken(IAccountManagerResponse response, final Account account,
final String authTokenType, final boolean notifyOnAuthFailure,
final boolean expectActivityLaunch, final Bundle loginOptions) {
@@ -956,36 +994,36 @@
installNotification(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
}
- private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
- AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
+ String getAccountLabel(String accountType) {
RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo =
- mAuthenticatorCache.getServiceInfo(
- AuthenticatorDescription.newKey(account.type));
+ mAuthenticatorCache.getServiceInfo(
+ AuthenticatorDescription.newKey(accountType));
if (serviceInfo == null) {
- throw new IllegalArgumentException("unknown account type: " + account.type);
+ throw new IllegalArgumentException("unknown account type: " + accountType);
}
final Context authContext;
try {
authContext = mContext.createPackageContext(
- serviceInfo.type.packageName, 0);
+ serviceInfo.type.packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException("unknown account type: " + account.type);
+ throw new IllegalArgumentException("unknown account type: " + accountType);
}
+ return authContext.getString(serviceInfo.type.labelId);
+ }
+
+ private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
+ AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(
String.valueOf(getCredentialPermissionNotificationId(account, authTokenType, uid)));
+
intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
- intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL, authTokenLabel);
intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
- intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT_TYPE_LABEL,
- authContext.getString(serviceInfo.type.labelId));
- intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_PACKAGES,
- mPackageManager.getPackagesForUid(uid));
intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, uid);
+
return intent;
}
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index fd340cbe..83e4fd9 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -17,6 +17,7 @@
import android.app.Activity;
import android.os.Bundle;
+import android.os.RemoteException;
import android.widget.TextView;
import android.widget.LinearLayout;
import android.widget.ImageView;
@@ -26,6 +27,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.RegisteredServicesCache;
import android.text.TextUtils;
import android.graphics.drawable.Drawable;
import com.android.internal.R;
@@ -46,6 +48,7 @@
private int mUid;
private Bundle mResultBundle = null;
protected LayoutInflater mInflater;
+ private final AccountManagerService accountManagerService = AccountManagerService.getSingleton();
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
@@ -55,27 +58,56 @@
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final Bundle extras = getIntent().getExtras();
+
+ // Grant 'account'/'type' to mUID
mAccount = extras.getParcelable(EXTRAS_ACCOUNT);
mAuthTokenType = extras.getString(EXTRAS_AUTH_TOKEN_TYPE);
+ mUid = extras.getInt(EXTRAS_REQUESTING_UID);
+ final PackageManager pm = getPackageManager();
+ final String[] packages = pm.getPackagesForUid(mUid);
- if (mAccount == null || mAuthTokenType == null) {
+ if (mAccount == null || mAuthTokenType == null || packages == null) {
// we were somehow started with bad parameters. abort the activity.
setResult(Activity.RESULT_CANCELED);
finish();
return;
}
- mUid = extras.getInt(EXTRAS_REQUESTING_UID);
- final String accountTypeLabel = extras.getString(EXTRAS_ACCOUNT_TYPE_LABEL);
- final String[] packages = extras.getStringArray(EXTRAS_PACKAGES);
- final String authTokenLabel = extras.getString(EXTRAS_AUTH_TOKEN_LABEL);
+ final String accountTypeLabel = accountManagerService.getAccountLabel(mAccount.type);
+
+
+ final TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
+ authTokenTypeView.setVisibility(View.GONE);
+
+ /** Handles the responses from the AccountManager */
+ IAccountManagerResponse response = new IAccountManagerResponse.Stub() {
+ public void onResult(Bundle bundle) {
+ final String authTokenLabel =
+ bundle.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
+ if (!TextUtils.isEmpty(authTokenLabel)) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if (!isFinishing()) {
+ authTokenTypeView.setText(authTokenLabel);
+ authTokenTypeView.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ }
+ }
+
+ public void onError(int code, String message) {
+ }
+ };
+
+ accountManagerService.getAuthTokenLabel(
+ response, mAccount, mAuthTokenType);
findViewById(R.id.allow_button).setOnClickListener(this);
findViewById(R.id.deny_button).setOnClickListener(this);
LinearLayout packagesListView = (LinearLayout) findViewById(R.id.packages_list);
- final PackageManager pm = getPackageManager();
for (String pkg : packages) {
String packageLabel;
try {
@@ -88,12 +120,6 @@
((TextView) findViewById(R.id.account_name)).setText(mAccount.name);
((TextView) findViewById(R.id.account_type)).setText(accountTypeLabel);
- TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
- if (TextUtils.isEmpty(authTokenLabel)) {
- authTokenTypeView.setVisibility(View.GONE);
- } else {
- authTokenTypeView.setText(authTokenLabel);
- }
}
private View newPackageView(String packageLabel) {
@@ -103,7 +129,6 @@
}
public void onClick(View v) {
- final AccountManagerService accountManagerService = AccountManagerService.getSingleton();
switch (v.getId()) {
case R.id.allow_button:
accountManagerService.grantAppPermission(mAccount, mAuthTokenType, mUid);
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 22e04a7..5fe3644 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -36,22 +36,36 @@
* this call, because all animation events are posted to a central timing loop so that animation
* times are all synchronized on a single timing pulse on the UI thread. So the animation will
* start the next time that event handler processes events.
+ *
+ * <p>The animation started by calling this method will be run on the thread that called
+ * this method. This thread should have a Looper on it (a runtime exception will be thrown if
+ * this is not the case). Also, if the animation will animate
+ * properties of objects in the view hierarchy, then the calling thread should be the UI
+ * thread for that view hierarchy.</p>
+ *
*/
public void start() {
}
/**
* Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to
- * stop in its tracks, sending an {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to
- * its listeners, followed by an {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message.
+ * stop in its tracks, sending an
+ * {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to
+ * its listeners, followed by an
+ * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message.
+ *
+ * <p>This method must be called on the thread that is running the animation.</p>
*/
public void cancel() {
}
/**
* Ends the animation. This causes the animation to assign the end value of the property being
- * animated, then calling the {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on
+ * animated, then calling the
+ * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on
* its listeners.
+ *
+ * <p>This method must be called on the thread that is running the animation.</p>
*/
public void end() {
}
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 154e084..d77dbdc 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -96,6 +96,9 @@
// The amount of time in ms to delay starting the animation after start() is called
private long mStartDelay = 0;
+ // Animator used for a nonzero startDelay
+ private ValueAnimator mDelayAnim = null;
+
// How long the child animations should last in ms. The default value is negative, which
// simply means that there is no duration set on the AnimatorSet. When a real duration is
@@ -276,6 +279,19 @@
listener.onAnimationCancel(this);
}
}
+ if (mDelayAnim != null && mDelayAnim.isRunning()) {
+ // If we're currently in the startDelay period, just cancel that animator and
+ // send out the end event to all listeners
+ mDelayAnim.cancel();
+ if (mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ for (AnimatorListener listener : tmpListeners) {
+ listener.onAnimationEnd(this);
+ }
+ }
+ return;
+ }
if (mSortedNodes.size() > 0) {
for (Node node : mSortedNodes) {
node.animation.cancel();
@@ -302,6 +318,9 @@
node.animation.addListener(mSetListener);
}
}
+ if (mDelayAnim != null) {
+ mDelayAnim.cancel();
+ }
if (mSortedNodes.size() > 0) {
for (Node node : mSortedNodes) {
node.animation.end();
@@ -411,12 +430,25 @@
// contains the animation nodes in the correct order.
sortNodes();
+ int numSortedNodes = mSortedNodes.size();
+ for (int i = 0; i < numSortedNodes; ++i) {
+ Node node = mSortedNodes.get(i);
+ // First, clear out the old listeners
+ ArrayList<AnimatorListener> oldListeners = node.animation.getListeners();
+ if (oldListeners != null && oldListeners.size() > 0) {
+ for (AnimatorListener listener : oldListeners) {
+ if (listener instanceof DependencyListener) {
+ node.animation.removeListener(listener);
+ }
+ }
+ }
+ }
+
// nodesToStart holds the list of nodes to be started immediately. We don't want to
// start the animations in the loop directly because we first need to set up
// dependencies on all of the nodes. For example, we don't want to start an animation
// when some other animation also wants to start when the first animation begins.
final ArrayList<Node> nodesToStart = new ArrayList<Node>();
- int numSortedNodes = mSortedNodes.size();
for (int i = 0; i < numSortedNodes; ++i) {
Node node = mSortedNodes.get(i);
if (mSetListener == null) {
@@ -443,19 +475,25 @@
}
} else {
// TODO: Need to cancel out of the delay appropriately
- ValueAnimator delayAnim = ValueAnimator.ofFloat(0f, 1f);
- delayAnim.setDuration(mStartDelay);
- delayAnim.addListener(new AnimatorListenerAdapter() {
+ mDelayAnim = ValueAnimator.ofFloat(0f, 1f);
+ mDelayAnim.setDuration(mStartDelay);
+ mDelayAnim.addListener(new AnimatorListenerAdapter() {
+ boolean canceled = false;
+ public void onAnimationCancel(Animator anim) {
+ canceled = true;
+ }
public void onAnimationEnd(Animator anim) {
- int numNodes = nodesToStart.size();
- for (int i = 0; i < numNodes; ++i) {
- Node node = nodesToStart.get(i);
- node.animation.start();
- mPlayingSet.add(node.animation);
+ if (!canceled) {
+ int numNodes = nodesToStart.size();
+ for (int i = 0; i < numNodes; ++i) {
+ Node node = nodesToStart.get(i);
+ node.animation.start();
+ mPlayingSet.add(node.animation);
+ }
}
}
});
- delayAnim.start();
+ mDelayAnim.start();
}
if (mListeners != null) {
ArrayList<AnimatorListener> tmpListeners =
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 7c2e70d..7f11871 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -19,6 +19,7 @@
import android.util.Log;
import java.lang.reflect.Method;
+import java.util.ArrayList;
/**
* This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
@@ -31,6 +32,7 @@
*
*/
public final class ObjectAnimator extends ValueAnimator {
+ private static final boolean DBG = false;
// The target object on which the property exists, set in the constructor
private Object mTarget;
@@ -265,6 +267,21 @@
}
}
+ @Override
+ public void start() {
+ if (DBG) {
+ Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
+ for (int i = 0; i < mValues.length; ++i) {
+ PropertyValuesHolder pvh = mValues[i];
+ ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
+ Log.d("ObjectAnimator", " Values[" + i + "]: " +
+ pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " +
+ keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue());
+ }
+ }
+ super.start();
+ }
+
/**
* This function is called immediately before processing the first animation
* frame of an animation. If there is a nonzero <code>startDelay</code>, the
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 97aa5a1..1412f38 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -178,9 +178,8 @@
* on the object. Also, if any value is null, the value will be filled in when the animation
* starts in the same way. This mechanism of automatically getting null values only works
* if the PropertyValuesHolder object is used in conjunction
- * {@link ObjectAnimator}, and with a getter function either
- * derived automatically from <code>propertyName</code> or set explicitly via
- * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+ * {@link ObjectAnimator}, and with a getter function
+ * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
* no way of determining what the value should be.
* @param propertyName The name of the property associated with this set of values. This
* can be the actual property name to be used when using a ObjectAnimator object, or
@@ -210,9 +209,8 @@
* on the object. Also, if any value is null, the value will be filled in when the animation
* starts in the same way. This mechanism of automatically getting null values only works
* if the PropertyValuesHolder object is used in conjunction
- * {@link ObjectAnimator}, and with a getter function either
- * derived automatically from <code>propertyName</code> or set explicitly via
- * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+ * {@link ObjectAnimator}, and with a getter function
+ * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
* no way of determining what the value should be.
*
* @param values One or more values that the animation will animate between.
@@ -229,9 +227,8 @@
* on the object. Also, if any value is null, the value will be filled in when the animation
* starts in the same way. This mechanism of automatically getting null values only works
* if the PropertyValuesHolder object is used in conjunction
- * {@link ObjectAnimator}, and with a getter function either
- * derived automatically from <code>propertyName</code> or set explicitly via
- * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+ * {@link ObjectAnimator}, and with a getter function
+ * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
* no way of determining what the value should be.
*
* @param values One or more values that the animation will animate between.
@@ -263,9 +260,8 @@
* on the object. Also, if any value is null, the value will be filled in when the animation
* starts in the same way. This mechanism of automatically getting null values only works
* if the PropertyValuesHolder object is used in conjunction
- * {@link ObjectAnimator}, and with a getter function either
- * derived automatically from <code>propertyName</code> or set explicitly via
- * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has
+ * {@link ObjectAnimator}, and with a getter function
+ * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
* no way of determining what the value should be.
*
* @param values One or more values that the animation will animate between.
@@ -329,7 +325,7 @@
// If we got here, then no appropriate function was found
Log.e("PropertyValuesHolder",
"Couldn't find setter/getter for property " + mPropertyName +
- "with value type "+ mValueType);
+ " with value type "+ mValueType);
}
return returnVal;
@@ -544,67 +540,6 @@
}
/**
- * Sets the <code>Method</code> that is called with the animated values calculated
- * during the animation. Setting the setter method is an alternative to supplying a
- * {@link #setPropertyName(String) propertyName} from which the method is derived. This
- * approach is more direct, and is especially useful when a function must be called that does
- * not correspond to the convention of <code>setName()</code>. For example, if a function
- * called <code>offset()</code> is to be called with the animated values, there is no way
- * to tell <code>ObjectAnimator</code> how to call that function simply through a property
- * name, so a setter method should be supplied instead.
- *
- * <p>Note that the setter function must take the same parameter type as the
- * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to
- * the setter function will fail.</p>
- *
- * @param setter The setter method that should be called with the animated values.
- */
- public void setSetter(Method setter) {
- mSetter = setter;
- }
-
- /**
- * Gets the <code>Method</code> that is called with the animated values calculated
- * during the animation.
- */
- public Method getSetter() {
- return mSetter;
- }
-
- /**
- * Sets the <code>Method</code> that is called to get unsupplied <code>valueFrom</code> or
- * <code>valueTo</code> properties. Setting the getter method is an alternative to supplying a
- * {@link #setPropertyName(String) propertyName} from which the method is derived. This
- * approach is more direct, and is especially useful when a function must be called that does
- * not correspond to the convention of <code>setName()</code>. For example, if a function
- * called <code>offset()</code> is to be called to get an initial value, there is no way
- * to tell <code>ObjectAnimator</code> how to call that function simply through a property
- * name, so a getter method should be supplied instead.
- *
- * <p>Note that the getter method is only called whether supplied here or derived
- * from the property name, if one of <code>valueFrom</code> or <code>valueTo</code> are
- * null. If both of those values are non-null, then there is no need to get one of the
- * values and the getter is not called.
- *
- * <p>Note that the getter function must return the same parameter type as the
- * <code>valueFrom</code> and <code>valueTo</code> properties (whichever of them are
- * non-null), otherwise the call to the getter function will fail.</p>
- *
- * @param getter The getter method that should be called to get initial animation values.
- */
- public void setGetter(Method getter) {
- mGetter = getter;
- }
-
- /**
- * Gets the <code>Method</code> that is called to get unsupplied <code>valueFrom</code> or
- * <code>valueTo</code> properties.
- */
- public Method getGetter() {
- return mGetter;
- }
-
- /**
* Sets the name of the property that will be animated. This name is used to derive
* a setter function that will be called to set animated values.
* For example, a property name of <code>foo</code> will result
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 8e541c2..1542c49 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -62,9 +62,7 @@
*/
private static final int STOPPED = 0; // Not yet playing
private static final int RUNNING = 1; // Playing normally
- private static final int CANCELED = 2; // cancel() called - need to end it
- private static final int ENDED = 3; // end() called - need to end it
- private static final int SEEKED = 4; // Seeked to some time value
+ private static final int SEEKED = 2; // Seeked to some time value
/**
* Internal variables
@@ -178,7 +176,7 @@
* Flag that represents the current state of the animation. Used to figure out when to start
* an animation (if state == STOPPED). Also used to end an animation that
* has been cancel()'d or end()'d since the last animation frame. Possible values are
- * STOPPED, RUNNING, ENDED, CANCELED.
+ * STOPPED, RUNNING, SEEKED.
*/
private int mPlayingState = STOPPED;
@@ -581,8 +579,7 @@
for (int i = 0; i < count; ++i) {
ValueAnimator anim = pendingCopy.get(i);
// If the animation has a startDelay, place it on the delayed list
- if (anim.mStartDelay == 0 || anim.mPlayingState == ENDED ||
- anim.mPlayingState == CANCELED) {
+ if (anim.mStartDelay == 0) {
anim.startAnimation();
} else {
delayedAnims.add(anim);
@@ -619,14 +616,28 @@
// Now process all active animations. The return value from animationFrame()
// tells the handler whether it should now be ended
int numAnims = animations.size();
- for (int i = 0; i < numAnims; ++i) {
+ int i = 0;
+ while (i < numAnims) {
ValueAnimator anim = animations.get(i);
if (anim.animationFrame(currentTime)) {
endingAnims.add(anim);
}
+ if (animations.size() == numAnims) {
+ ++i;
+ } else {
+ // An animation might be canceled or ended by client code
+ // during the animation frame. Check to see if this happened by
+ // seeing whether the current index is the same as it was before
+ // calling animationFrame(). Another approach would be to copy
+ // animations to a temporary list and process that list instead,
+ // but that entails garbage and processing overhead that would
+ // be nice to avoid.
+ --numAnims;
+ endingAnims.remove(anim);
+ }
}
if (endingAnims.size() > 0) {
- for (int i = 0; i < endingAnims.size(); ++i) {
+ for (i = 0; i < endingAnims.size(); ++i) {
endingAnims.get(i).endAnimation();
}
endingAnims.clear();
@@ -918,9 +929,7 @@
// to run
if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
sDelayedAnims.get().contains(this)) {
- // Just set the CANCELED flag - this causes the animation to end the next time a frame
- // is processed.
- mPlayingState = CANCELED;
+ endAnimation();
}
}
@@ -929,23 +938,21 @@
if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) {
// Special case if the animation has not yet started; get it ready for ending
mStartedDelay = false;
- sPendingAnimations.get().add(this);
- AnimationHandler animationHandler = sAnimationHandler.get();
- if (animationHandler == null) {
- animationHandler = new AnimationHandler();
- sAnimationHandler.set(animationHandler);
- }
- animationHandler.sendEmptyMessage(ANIMATION_START);
+ startAnimation();
}
- // Just set the ENDED flag - this causes the animation to end the next time a frame
- // is processed.
- mPlayingState = ENDED;
+ // The final value set on the target varies, depending on whether the animation
+ // was supposed to repeat an odd number of times
+ if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
+ animateValue(0f);
+ } else {
+ animateValue(1f);
+ }
+ endAnimation();
}
@Override
public boolean isRunning() {
- // ENDED or CANCELED indicate that it has been ended or canceled, but not processed yet
- return (mPlayingState == RUNNING || mPlayingState == ENDED || mPlayingState == CANCELED);
+ return (mPlayingState == RUNNING);
}
/**
@@ -973,6 +980,8 @@
*/
private void endAnimation() {
sAnimations.get().remove(this);
+ sPendingAnimations.get().remove(this);
+ sDelayedAnims.get().remove(this);
mPlayingState = STOPPED;
if (mListeners != null) {
ArrayList<AnimatorListener> tmpListeners =
@@ -1014,10 +1023,6 @@
* should be added to the set of active animations.
*/
private boolean delayedAnimationFrame(long currentTime) {
- if (mPlayingState == CANCELED || mPlayingState == ENDED) {
- // end the delay, process an animation frame to actually cancel it
- return true;
- }
if (!mStartedDelay) {
mStartedDelay = true;
mDelayStartTime = currentTime;
@@ -1088,19 +1093,6 @@
}
animateValue(fraction);
break;
- case ENDED:
- // The final value set on the target varies, depending on whether the animation
- // was supposed to repeat an odd number of times
- if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
- animateValue(0f);
- } else {
- animateValue(1f);
- }
- // Fall through to set done flag
- case CANCELED:
- done = true;
- mPlayingState = STOPPED;
- break;
}
return done;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d2de382..f1842c6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -532,10 +532,6 @@
throw new RuntimeException("Not supported in system context");
}
- static File makeBackupFile(File prefsFile) {
- return new File(prefsFile.getPath() + ".bak");
- }
-
public File getSharedPrefsFile(String name) {
return makeFilename(getPreferencesDir(), name + ".xml");
}
@@ -543,54 +539,19 @@
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
SharedPreferencesImpl sp;
- File prefsFile;
- boolean needInitialLoad = false;
synchronized (sSharedPrefs) {
sp = sSharedPrefs.get(name);
- if (sp != null && !sp.hasFileChangedUnexpectedly()) {
- return sp;
- }
- prefsFile = getSharedPrefsFile(name);
if (sp == null) {
- sp = new SharedPreferencesImpl(prefsFile, mode, null);
+ File prefsFile = getSharedPrefsFile(name);
+ sp = new SharedPreferencesImpl(prefsFile, mode);
sSharedPrefs.put(name, sp);
- needInitialLoad = true;
- }
- }
-
- synchronized (sp) {
- if (needInitialLoad && sp.isLoaded()) {
- // lost the race to load; another thread handled it
return sp;
}
- File backup = makeBackupFile(prefsFile);
- if (backup.exists()) {
- prefsFile.delete();
- backup.renameTo(prefsFile);
- }
-
- // Debugging
- if (prefsFile.exists() && !prefsFile.canRead()) {
- Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission");
- }
-
- Map map = null;
- FileStatus stat = new FileStatus();
- if (FileUtils.getFileStatus(prefsFile.getPath(), stat) && prefsFile.canRead()) {
- try {
- FileInputStream str = new FileInputStream(prefsFile);
- map = XmlUtils.readMapXml(str);
- str.close();
- } catch (XmlPullParserException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "getSharedPreferences", e);
- } catch (IOException e) {
- Log.w(TAG, "getSharedPreferences", e);
- }
- }
- sp.replace(map, stat);
}
+ // If somebody else (some other process) changed the prefs
+ // file behind our back, we reload it. This has been the
+ // historical (if undocumented) behavior.
+ sp.startReloadIfChangedUnexpectedly();
return sp;
}
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 37f8738..efe527f 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -16,23 +16,18 @@
package android.app;
+import com.android.internal.R;
+
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Build;
import android.os.Bundle;
-import android.text.TextUtils.TruncateAt;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;
-import android.widget.TextView;
import android.widget.DatePicker.OnDateChangedListener;
-import com.android.internal.R;
-
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-
/**
* A simple dialog containing an {@link android.widget.DatePicker}.
*
@@ -48,13 +43,6 @@
private final DatePicker mDatePicker;
private final OnDateSetListener mCallBack;
- private final Calendar mCalendar;
- private final java.text.DateFormat mTitleDateFormat;
- private final String[] mWeekDays;
-
- private int mInitialYear;
- private int mInitialMonth;
- private int mInitialDay;
/**
* The callback used to indicate the user is done filling in the date.
@@ -106,40 +94,18 @@
super(context, theme);
mCallBack = callBack;
- mInitialYear = year;
- mInitialMonth = monthOfYear;
- mInitialDay = dayOfMonth;
- DateFormatSymbols symbols = new DateFormatSymbols();
- mWeekDays = symbols.getShortWeekdays();
-
- mTitleDateFormat = java.text.DateFormat.
- getDateInstance(java.text.DateFormat.FULL);
- mCalendar = Calendar.getInstance();
- updateTitle(mInitialYear, mInitialMonth, mInitialDay);
setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set), this);
setButton(BUTTON_NEGATIVE, context.getText(R.string.cancel), (OnClickListener) null);
- setIcon(R.drawable.ic_dialog_time);
+ setIcon(0);
+ setTitle(R.string.date_picker_dialog_title);
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.date_picker_dialog, null);
setView(view);
mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
- mDatePicker.init(mInitialYear, mInitialMonth, mInitialDay, this);
- }
-
- @Override
- public void show() {
- super.show();
-
- /* Sometimes the full month is displayed causing the title
- * to be very long, in those cases ensure it doesn't wrap to
- * 2 lines (as that looks jumpy) and ensure we ellipsize the end.
- */
- TextView title = (TextView) findViewById(R.id.alertTitle);
- title.setSingleLine();
- title.setEllipsize(TruncateAt.END);
+ mDatePicker.init(year, monthOfYear, dayOfMonth, this);
}
public void onClick(DialogInterface dialog, int which) {
@@ -152,23 +118,13 @@
public void onDateChanged(DatePicker view, int year,
int month, int day) {
- updateTitle(year, month, day);
+ mDatePicker.init(year, month, day, null);
}
public void updateDate(int year, int monthOfYear, int dayOfMonth) {
- mInitialYear = year;
- mInitialMonth = monthOfYear;
- mInitialDay = dayOfMonth;
mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
}
- private void updateTitle(int year, int month, int day) {
- mCalendar.set(Calendar.YEAR, year);
- mCalendar.set(Calendar.MONTH, month);
- mCalendar.set(Calendar.DAY_OF_MONTH, day);
- setTitle(mTitleDateFormat.format(mCalendar.getTime()));
- }
-
@Override
public Bundle onSaveInstanceState() {
Bundle state = super.onSaveInstanceState();
@@ -185,6 +141,5 @@
int month = savedInstanceState.getInt(MONTH);
int day = savedInstanceState.getInt(DAY);
mDatePicker.init(year, month, day, this);
- updateTitle(year, month, day);
}
}
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index a807d3b..8aee65c 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -25,9 +25,12 @@
import com.google.android.collect.Maps;
import com.android.internal.util.XmlUtils;
+import dalvik.system.BlockGuard;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -61,32 +64,88 @@
private final Object mWritingToDiskLock = new Object();
private static final Object mContent = new Object();
- private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
+ private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
+ new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
- SharedPreferencesImpl(
- File file, int mode, Map initialContents) {
+ SharedPreferencesImpl(File file, int mode) {
mFile = file;
- mBackupFile = ContextImpl.makeBackupFile(file);
+ mBackupFile = makeBackupFile(file);
mMode = mode;
- mLoaded = initialContents != null;
- mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
- FileStatus stat = new FileStatus();
- if (FileUtils.getFileStatus(file.getPath(), stat)) {
- mStatTimestamp = stat.mtime;
- }
- mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
+ mLoaded = false;
+ mMap = null;
+ startLoadFromDisk();
}
- // Has this SharedPreferences ever had values assigned to it?
- boolean isLoaded() {
+ private void startLoadFromDisk() {
synchronized (this) {
- return mLoaded;
+ mLoaded = false;
+ }
+ new Thread("SharedPreferencesImpl-load") {
+ public void run() {
+ synchronized (SharedPreferencesImpl.this) {
+ loadFromDiskLocked();
+ }
+ }
+ }.start();
+ }
+
+ private void loadFromDiskLocked() {
+ if (mLoaded) {
+ return;
+ }
+ if (mBackupFile.exists()) {
+ mFile.delete();
+ mBackupFile.renameTo(mFile);
+ }
+
+ // Debugging
+ if (mFile.exists() && !mFile.canRead()) {
+ Log.w(TAG, "Attempt to read preferences file " + mFile + " without permission");
+ }
+
+ Map map = null;
+ FileStatus stat = new FileStatus();
+ if (FileUtils.getFileStatus(mFile.getPath(), stat) && mFile.canRead()) {
+ try {
+ FileInputStream str = new FileInputStream(mFile);
+ map = XmlUtils.readMapXml(str);
+ str.close();
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "getSharedPreferences", e);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "getSharedPreferences", e);
+ } catch (IOException e) {
+ Log.w(TAG, "getSharedPreferences", e);
+ }
+ }
+ mLoaded = true;
+ if (map != null) {
+ mMap = map;
+ mStatTimestamp = stat.mtime;
+ mStatSize = stat.size;
+ } else {
+ mMap = new HashMap<String, Object>();
+ }
+ notifyAll();
+ }
+
+ private static File makeBackupFile(File prefsFile) {
+ return new File(prefsFile.getPath() + ".bak");
+ }
+
+ void startReloadIfChangedUnexpectedly() {
+ synchronized (this) {
+ // TODO: wait for any pending writes to disk?
+ if (!hasFileChangedUnexpectedly()) {
+ return;
+ }
+ startLoadFromDisk();
}
}
// Has the file changed out from under us? i.e. writes that
// we didn't instigate.
- public boolean hasFileChangedUnexpectedly() {
+ private boolean hasFileChangedUnexpectedly() {
synchronized (this) {
if (mDiskWritesInFlight > 0) {
// If we know we caused it, it's not unexpected.
@@ -103,19 +162,6 @@
}
}
- /*package*/ void replace(Map newContents, FileStatus stat) {
- synchronized (this) {
- mLoaded = true;
- if (newContents != null) {
- mMap = newContents;
- }
- if (stat != null) {
- mStatTimestamp = stat.mtime;
- mStatSize = stat.size;
- }
- }
- }
-
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.put(listener, mContent);
@@ -128,8 +174,24 @@
}
}
+ private void awaitLoadedLocked() {
+ if (!mLoaded) {
+ // Raise an explicit StrictMode onReadFromDisk for this
+ // thread, since the real read will be in a different
+ // thread and otherwise ignored by StrictMode.
+ BlockGuard.getThreadPolicy().onReadFromDisk();
+ }
+ while (!mLoaded) {
+ try {
+ wait();
+ } catch (InterruptedException unused) {
+ }
+ }
+ }
+
public Map<String, ?> getAll() {
- synchronized(this) {
+ synchronized (this) {
+ awaitLoadedLocked();
//noinspection unchecked
return new HashMap<String, Object>(mMap);
}
@@ -137,6 +199,7 @@
public String getString(String key, String defValue) {
synchronized (this) {
+ awaitLoadedLocked();
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
@@ -144,6 +207,7 @@
public Set<String> getStringSet(String key, Set<String> defValues) {
synchronized (this) {
+ awaitLoadedLocked();
Set<String> v = (Set<String>) mMap.get(key);
return v != null ? v : defValues;
}
@@ -151,24 +215,28 @@
public int getInt(String key, int defValue) {
synchronized (this) {
+ awaitLoadedLocked();
Integer v = (Integer)mMap.get(key);
return v != null ? v : defValue;
}
}
public long getLong(String key, long defValue) {
synchronized (this) {
+ awaitLoadedLocked();
Long v = (Long)mMap.get(key);
return v != null ? v : defValue;
}
}
public float getFloat(String key, float defValue) {
synchronized (this) {
+ awaitLoadedLocked();
Float v = (Float)mMap.get(key);
return v != null ? v : defValue;
}
}
public boolean getBoolean(String key, boolean defValue) {
synchronized (this) {
+ awaitLoadedLocked();
Boolean v = (Boolean)mMap.get(key);
return v != null ? v : defValue;
}
@@ -176,11 +244,23 @@
public boolean contains(String key) {
synchronized (this) {
+ awaitLoadedLocked();
return mMap.containsKey(key);
}
}
public Editor edit() {
+ // TODO: remove the need to call awaitLoadedLocked() when
+ // requesting an editor. will require some work on the
+ // Editor, but then we should be able to do:
+ //
+ // context.getSharedPreferences(..).edit().putString(..).apply()
+ //
+ // ... all without blocking.
+ synchronized (this) {
+ awaitLoadedLocked();
+ }
+
return new EditorImpl();
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 27be51a..b27f4cf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -803,7 +803,7 @@
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
- * @param receiverPermission (optional) String naming a permissions that
+ * @param receiverPermission (optional) String naming a permission that
* a receiver must hold in order to receive your broadcast.
* If null, no permission is required.
*
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 1b799ae..4a75514 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1532,7 +1532,7 @@
* </ul>
*
* <p>
- * <center><img src="../../../images/axis_device_inverted.png"
+ * <center><img src="../../../images/axis_globe_inverted.png"
* alt="Inverted world coordinate-system diagram." border="0" /></center>
* </p>
* <p>
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ecfa2c1..3d685cb 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -212,10 +212,13 @@
* default connections.
*/
public static final int TYPE_WIMAX = 6;
+
+ /** {@hide} */
+ public static final int TYPE_DUMMY = 7;
/** {@hide} TODO: Need to adjust this for WiMAX. */
public static final int MAX_RADIO_TYPE = TYPE_WIFI;
/** {@hide} TODO: Need to adjust this for WiMAX. */
- public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_HIPRI;
+ public static final int MAX_NETWORK_TYPE = TYPE_DUMMY;
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
new file mode 100644
index 0000000..daa1c09
--- /dev/null
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkInfo;
+import android.net.LinkProperties;
+import android.util.Slog;
+
+/**
+ * A dummy data state tracker for use when we don't have a real radio
+ * connection. useful when bringing up a board or when you have network
+ * access through other means.
+ *
+ * {@hide}
+ */
+public class DummyDataStateTracker implements NetworkStateTracker {
+
+ private static final String TAG = "DummyDataStateTracker";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ private NetworkInfo mNetworkInfo;
+ private boolean mTeardownRequested = false;
+ private Handler mTarget;
+ private Context mContext;
+ private LinkProperties mLinkProperties;
+ private LinkCapabilities mLinkCapabilities;
+ 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;
+
+ /**
+ * Create a new DummyDataStateTracker
+ * @param netType the ConnectivityManager network type
+ * @param tag the name of this network
+ */
+ public DummyDataStateTracker(int netType, String tag) {
+ mNetworkInfo = new NetworkInfo(netType);
+ }
+
+ /**
+ * Begin monitoring data connectivity.
+ *
+ * @param context is the current Android context
+ * @param target is the Handler to which to return the events.
+ */
+ public void startMonitoring(Context context, Handler target) {
+ mTarget = target;
+ mContext = context;
+ }
+
+ /**
+ * Return the IP addresses of the DNS servers available for the mobile data
+ * network interface.
+ * @return a list of DNS addresses, with no holes.
+ */
+ public String[] getDnsPropNames() {
+ return new String[0];
+ }
+
+ public boolean isPrivateDnsRouteSet() {
+ return mPrivateDnsRouteSet;
+ }
+
+ public void privateDnsRouteSet(boolean enabled) {
+ mPrivateDnsRouteSet = enabled;
+ }
+
+ public NetworkInfo getNetworkInfo() {
+ return mNetworkInfo;
+ }
+
+ public int getDefaultGatewayAddr() {
+ return 0;
+ }
+
+ public boolean isDefaultRouteSet() {
+ return mDefaultRouteSet;
+ }
+
+ public void defaultRouteSet(boolean enabled) {
+ mDefaultRouteSet = enabled;
+ }
+
+ /**
+ * This is not implemented.
+ */
+ public void releaseWakeLock() {
+ }
+
+ /**
+ * Report whether data connectivity is possible.
+ */
+ public boolean isAvailable() {
+ return true;
+ }
+
+ /**
+ * Return the system properties name associated with the tcp buffer sizes
+ * for this network.
+ */
+ public String getTcpBufferSizesPropName() {
+ return "net.tcp.buffersize.unknown";
+ }
+
+ /**
+ * Tear down mobile data connectivity, i.e., disable the ability to create
+ * mobile data connections.
+ * TODO - make async and return nothing?
+ */
+ public boolean teardown() {
+ setDetailedState(NetworkInfo.DetailedState.DISCONNECTING, "disabled", null);
+ setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, "disabled", null);
+ return true;
+ }
+
+ /**
+ * Record the detailed state of a network, and if it is a
+ * change from the previous state, send a notification to
+ * any listeners.
+ * @param state the new @{code DetailedState}
+ * @param reason a {@code String} indicating a reason for the state change,
+ * if one was supplied. May be {@code null}.
+ * @param extraInfo optional {@code String} providing extra information about the state change
+ */
+ private void setDetailedState(NetworkInfo.DetailedState state, String reason,
+ String extraInfo) {
+ if (DBG) log("setDetailed state, old ="
+ + mNetworkInfo.getDetailedState() + " and new state=" + state);
+ mNetworkInfo.setDetailedState(state, reason, extraInfo);
+ Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+ }
+
+ public void setTeardownRequested(boolean isRequested) {
+ mTeardownRequested = isRequested;
+ }
+
+ public boolean isTeardownRequested() {
+ return mTeardownRequested;
+ }
+
+ /**
+ * Re-enable mobile data connectivity after a {@link #teardown()}.
+ * TODO - make async and always get a notification?
+ */
+ public boolean reconnect() {
+ setDetailedState(NetworkInfo.DetailedState.CONNECTING, "enabled", null);
+ setDetailedState(NetworkInfo.DetailedState.CONNECTED, "enabled", null);
+ setTeardownRequested(false);
+ return true;
+ }
+
+ /**
+ * Turn on or off the mobile radio. No connectivity will be possible while the
+ * radio is off. The operation is a no-op if the radio is already in the desired state.
+ * @param turnOn {@code true} if the radio should be turned on, {@code false} if
+ */
+ public boolean setRadio(boolean turnOn) {
+ return true;
+ }
+
+ public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+ return -1;
+ }
+
+ public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+ return -1;
+ }
+
+ public void setDataEnable(boolean enabled) {
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer("Dummy data state: none, dummy!");
+ return sb.toString();
+ }
+
+ /**
+ * @see android.net.NetworkStateTracker#getLinkProperties()
+ */
+ public LinkProperties getLinkProperties() {
+ return new LinkProperties(mLinkProperties);
+ }
+
+ /**
+ * @see android.net.NetworkStateTracker#getLinkCapabilities()
+ */
+ public LinkCapabilities getLinkCapabilities() {
+ return new LinkCapabilities(mLinkCapabilities);
+ }
+
+ static private void log(String s) {
+ Slog.d(TAG, s);
+ }
+
+ static private void loge(String s) {
+ Slog.e(TAG, s);
+ }
+}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 4df8db5..b3a354f 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -20,14 +20,21 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Messenger;
import android.os.RemoteException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.ServiceManager;
+
+import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.AsyncChannel;
+
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo;
import android.net.LinkProperties;
@@ -67,6 +74,10 @@
// the other is also disconnected before we reset sockets
private boolean mIsDefaultOrHipri = false;
+ private Handler mHandler;
+ private AsyncChannel mDataConnectionTrackerAc;
+ private Messenger mMessenger;
+
/**
* Create a new MobileDataStateTracker
* @param netType the ConnectivityManager network type
@@ -107,14 +118,54 @@
mTarget = target;
mContext = context;
+ HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
+ handlerThread.start();
+ mHandler = new MdstHandler(handlerThread.getLooper(), this);
+
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
+ filter.addAction(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
mContext.registerReceiver(new MobileDataStateReceiver(), filter);
mMobileDataState = Phone.DataState.DISCONNECTED;
}
+ static class MdstHandler extends Handler {
+ private MobileDataStateTracker mMdst;
+
+ MdstHandler(Looper looper, MobileDataStateTracker mdst) {
+ super(looper);
+ mMdst = mdst;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ if (DBG) {
+ mMdst.log("MdstHandler connected");
+ }
+ mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj;
+ } else {
+ if (DBG) {
+ mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1);
+ }
+ }
+ break;
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+ mMdst.log("Disconnected from DataStateTracker");
+ mMdst.mDataConnectionTrackerAc = null;
+ break;
+ default: {
+ mMdst.log("Ignorning unknown message=" + msg);
+ break;
+ }
+ }
+ }
+ }
+
/**
* Return the IP addresses of the DNS servers available for the mobile data
* network interface.
@@ -179,7 +230,7 @@
false));
if (DBG) {
- log(mApnType + " Received state=" + state + ", old=" + mMobileDataState +
+ log("Received state=" + state + ", old=" + mMobileDataState +
", reason=" + (reason == null ? "(unspecified)" : reason));
}
if (mMobileDataState != state) {
@@ -265,10 +316,16 @@
String reason = intent.getStringExtra(Phone.FAILURE_REASON_KEY);
String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
if (DBG) {
- log(mApnType + "Received " + intent.getAction() +
+ log("Received " + intent.getAction() +
" broadcast" + reason == null ? "" : "(" + reason + ")");
}
setDetailedState(DetailedState.FAILED, reason, apnName);
+ } else if (intent.getAction().
+ equals(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {
+ if (DBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
+ mMessenger = intent.getParcelableExtra(DataConnectionTracker.EXTRA_MESSENGER);
+ AsyncChannel ac = new AsyncChannel();
+ ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger);
} else {
if (DBG) log("Broadcast received: ignore " + intent.getAction());
}
@@ -488,6 +545,20 @@
return -1;
}
+ /**
+ * @param enabled
+ */
+ public void setDataEnable(boolean enabled) {
+ try {
+ log("setDataEnable: E enabled=" + enabled);
+ mDataConnectionTrackerAc.sendMessage(DataConnectionTracker.CMD_SET_DATA_ENABLE,
+ enabled ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED);
+ log("setDataEnable: X enabled=" + enabled);
+ } catch (Exception e) {
+ log("setDataEnable: X mAc was null" + e);
+ }
+ }
+
@Override
public String toString() {
StringBuffer sb = new StringBuffer("Mobile data state: ");
@@ -543,7 +614,7 @@
case ConnectivityManager.TYPE_MOBILE_HIPRI:
return Phone.APN_TYPE_HIPRI;
default:
- loge("Error mapping networkType " + netType + " to apnType.");
+ sloge("Error mapping networkType " + netType + " to apnType.");
return null;
}
}
@@ -562,11 +633,15 @@
return new LinkCapabilities(mLinkCapabilities);
}
- static private void log(String s) {
- Slog.d(TAG, s);
+ private void log(String s) {
+ Slog.d(TAG, mApnType + ": " + s);
}
- static private void loge(String s) {
+ private void loge(String s) {
+ Slog.e(TAG, mApnType + ": " + s);
+ }
+
+ static private void sloge(String s) {
Slog.e(TAG, s);
}
}
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 8afdcee..e378506 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -169,6 +169,11 @@
public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid);
/**
+ * @param enabled
+ */
+ public void setDataEnable(boolean enabled);
+
+ /**
* -------------------------------------------------------------
* Storage API used by ConnectivityService for saving
* Network specific information.
@@ -204,5 +209,4 @@
* Indicate tear down requested from connectivity
*/
public void setTeardownRequested(boolean isRequested);
-
}
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 04304dd..ad05496 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -154,6 +154,7 @@
case TagTechnology.NFC_V: {
return new NfcV(adapter, this, extras);
}
+ case TagTechnology.MIFARE_CLASSIC_NDEF:
case TagTechnology.TYPE_1:
case TagTechnology.TYPE_2:
case TagTechnology.TYPE_3:
diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/technology/MifareClassic.java
index c25b71f..ba3a425 100644
--- a/core/java/android/nfc/technology/MifareClassic.java
+++ b/core/java/android/nfc/technology/MifareClassic.java
@@ -36,23 +36,21 @@
*/
public final class MifareClassic extends BasicTagTechnology {
/**
- * The well-known, default factory MIFARE read key.
+ * The well-known, default MIFARE read key.
* Use this key to effectively make the payload in this sector
* public.
*/
- public static final byte[] DEFAULT_KEY_FACTORY =
+ public static final byte[] KEY_DEFAULT =
{(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
- public static final byte[] DEFAULT_KEY_ZERO =
- {(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00};
/**
* The well-known, default Mifare Application Directory read key.
*/
- public static final byte[] DEFAULT_KEY_MAD =
+ public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY =
{(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5};
/**
* The well-known, default read key for NDEF data on a Mifare Classic
*/
- public static final byte[] DEFAULT_KEY_NFC_FORUM =
+ public static final byte[] KEY_NFC_FORUM =
{(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
public static final int TYPE_CLASSIC = 0;
diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/technology/NdefFormatable.java
new file mode 100644
index 0000000..7c4f9ab
--- /dev/null
+++ b/core/java/android/nfc/technology/NdefFormatable.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.ErrorCodes;
+import android.nfc.FormatException;
+import android.nfc.NdefMessage;
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import java.io.IOException;
+
+/**
+ * An interface to a {@link Tag} allowing to format the tag as NDEF.
+ *
+ * <p>You can acquire this kind of interface with {@link Tag#getTechnology(int)}.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NdefFormatable extends BasicTagTechnology {
+ /**
+ * Internal constructor, to be used by NfcAdapter
+ * @hide
+ */
+ public NdefFormatable(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
+ super(adapter, tag, tech);
+ }
+
+ /**
+ * Returns whether a tag can be formatted with {@link
+ * NdefFormatable#format(NdefMessage)}
+ */
+ public boolean canBeFormatted() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Formats a tag as NDEF, if possible. You may supply a first
+ * NdefMessage to be written on the tag.
+ */
+ public void format(NdefMessage firstMessage) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java
index 2b4f74c..9dfb297 100644
--- a/core/java/android/nfc/technology/TagTechnology.java
+++ b/core/java/android/nfc/technology/TagTechnology.java
@@ -67,6 +67,11 @@
public static final int TYPE_4 = 104;
/**
+ * This object is an instance of {@link NdefFormatable}
+ */
+ public static final int NDEF_FORMATABLE = 110;
+
+ /**
* This object is an instance of {@link MifareClassic}
*/
public static final int MIFARE_CLASSIC = 200;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ed71da2..1e80da7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -977,6 +977,9 @@
public static float getFloat(ContentResolver cr, String name)
throws SettingNotFoundException {
String v = getString(cr, name);
+ if (v == null) {
+ throw new SettingNotFoundException(name);
+ }
try {
return Float.parseFloat(v);
} catch (NumberFormatException e) {
@@ -1577,7 +1580,7 @@
* Default screen rotation when no other policy applies.
* When {@link #ACCELEROMETER_ROTATION} is zero and no on-screen Activity expresses a
* preference, this rotation value will be used. Must be one of the
- * {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
+ * {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
*
* @see Display#getRotation
*/
@@ -2296,6 +2299,9 @@
public static float getFloat(ContentResolver cr, String name)
throws SettingNotFoundException {
String v = getString(cr, name);
+ if (v == null) {
+ throw new SettingNotFoundException(name);
+ }
try {
return Float.parseFloat(v);
} catch (NumberFormatException e) {
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index c05a8fe..c6ffe58 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -42,6 +42,12 @@
public static final int EPOCH_JULIAN_DAY = 2440588;
/**
+ * The Julian day of the Monday in the week of the epoch, December 29, 1969
+ * on the Gregorian calendar.
+ */
+ public static final int MONDAY_BEFORE_JULIAN_EPOCH = EPOCH_JULIAN_DAY - 3;
+
+ /**
* True if this is an allDay event. The hour, minute, second fields are
* all zero, and the date is displayed the same in all time zones.
*/
@@ -770,4 +776,39 @@
millis = normalize(true);
return millis;
}
+
+ /**
+ * Returns the week since {@link #EPOCH_JULIAN_DAY} (Jan 1, 1970) adjusted
+ * for first day of week. This takes a julian day and the week start day and
+ * calculates which week since {@link #EPOCH_JULIAN_DAY} that day occurs in,
+ * starting at 0. *Do not* use this to compute the ISO week number for the
+ * year.
+ *
+ * @param julianDay The julian day to calculate the week number for
+ * @param firstDayOfWeek Which week day is the first day of the week, see
+ * {@link #SUNDAY}
+ * @return Weeks since the epoch
+ */
+ public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) {
+ int diff = THURSDAY - firstDayOfWeek;
+ if (diff < 0) {
+ diff += 7;
+ }
+ int refDay = EPOCH_JULIAN_DAY - diff;
+ return (julianDay - refDay) / 7;
+ }
+
+ /**
+ * Takes a number of weeks since the epoch and calculates the Julian day of
+ * the Monday for that week. This assumes that the week containing the
+ * {@link #EPOCH_JULIAN_DAY} is considered week 0. It returns the Julian day
+ * for the Monday week weeks after the Monday of the week containing the
+ * epoch.
+ *
+ * @param week Number of weeks since the epoch
+ * @return The julian day for the Monday of the given week since the epoch
+ */
+ public static int getJulianMondayFromWeeksSinceEpoch(int week) {
+ return MONDAY_BEFORE_JULIAN_EPOCH + week * 7;
+ }
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index a34fe87..53cff91 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1101,7 +1101,9 @@
}
}
- if (hwInitialized || (windowShouldResize && mAttachInfo.mHardwareRenderer != null)) {
+ if (hwInitialized || (windowShouldResize &&
+ mAttachInfo.mHardwareRenderer != null &&
+ mAttachInfo.mHardwareRenderer.isEnabled())) {
mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
}
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 8f92458..2c38c93 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -599,13 +599,20 @@
public void addJavascriptInterface(Object obj, String interfaceName) {
assert obj != null;
+ removeJavascriptInterface(interfaceName);
if (mJSInterfaceMap == null) {
mJSInterfaceMap = new HashMap<String, Object>();
}
+ mJSInterfaceMap.put(interfaceName, obj);
+ }
+
+ public void removeJavascriptInterface(String interfaceName) {
+ if (mJSInterfaceMap == null) {
+ return;
+ }
if (mJSInterfaceMap.containsKey(interfaceName)) {
mJSInterfaceMap.remove(interfaceName);
}
- mJSInterfaceMap.put(interfaceName, obj);
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index bb8f5d7..bf8f7db 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -434,9 +434,9 @@
private float mLastVelX;
private float mLastVelY;
- // A pointer to the native scrollable layer when dragging layers. Only
- // valid when mTouchMode is TOUCH_DRAG_LAYER_MODE.
+ // The id of the native layer being scrolled.
private int mScrollingLayer;
+ private Rect mScrollingLayerRect = new Rect();
// only trigger accelerated fling if the new velocity is at least
// MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION times of the previous velocity
@@ -2646,6 +2646,15 @@
@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX,
boolean clampedY) {
+ // Special-case layer scrolling so that we do not trigger normal scroll
+ // updating.
+ if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+ nativeScrollLayer(mScrollingLayer, scrollX, scrollY);
+ mScrollingLayerRect.left = scrollX;
+ mScrollingLayerRect.top = scrollY;
+ invalidate();
+ return;
+ }
mInOverScrollMode = false;
int maxX = computeMaxScrollX();
int maxY = computeMaxScrollY();
@@ -3048,18 +3057,37 @@
invalidate(); // So we draw again
if (!mScroller.isFinished()) {
- final int rangeX = computeMaxScrollX();
- final int rangeY = computeMaxScrollY();
+ int rangeX = computeMaxScrollX();
+ int rangeY = computeMaxScrollY();
+ int overflingDistance = mOverflingDistance;
+
+ // Use the layer's scroll data if needed.
+ if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+ oldX = mScrollingLayerRect.left;
+ oldY = mScrollingLayerRect.top;
+ rangeX = mScrollingLayerRect.right;
+ rangeY = mScrollingLayerRect.bottom;
+ // No overscrolling for layers.
+ overflingDistance = 0;
+ }
+
overScrollBy(x - oldX, y - oldY, oldX, oldY,
rangeX, rangeY,
- mOverflingDistance, mOverflingDistance, false);
+ overflingDistance, overflingDistance, false);
if (mOverScrollGlow != null) {
mOverScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY);
}
} else {
- mScrollX = x;
- mScrollY = y;
+ if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+ mScrollX = x;
+ mScrollY = y;
+ } else {
+ // Update the layer position instead of WebView.
+ nativeScrollLayer(mScrollingLayer, x, y);
+ mScrollingLayerRect.left = x;
+ mScrollingLayerRect.top = y;
+ }
abortAnimation();
mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
WebViewCore.resumePriority();
@@ -3495,7 +3523,8 @@
* </ul></p>
* @param obj The class instance to bind to Javascript, null instances are
* ignored.
- * @param interfaceName The name to used to expose the class in JavaScript.
+ * @param interfaceName The name to used to expose the instance in
+ * JavaScript.
*/
public void addJavascriptInterface(Object obj, String interfaceName) {
if (obj == null) {
@@ -3508,6 +3537,16 @@
}
/**
+ * Removes a previously added JavaScript interface with the given name.
+ * @param interfaceName The name of the interface to remove.
+ */
+ public void removeJavascriptInterface(String interfaceName) {
+ WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
+ arg.mInterfaceName = interfaceName;
+ mWebViewCore.sendMessage(EventHub.REMOVE_JS_INTERFACE, arg);
+ }
+
+ /**
* Return the WebSettings object used to control the settings for this
* WebView.
* @return A WebSettings object that can be used to control this WebView's
@@ -4828,6 +4867,11 @@
/* package */ void setFocusControllerActive(boolean active) {
if (mWebViewCore == null) return;
mWebViewCore.sendMessage(EventHub.SET_ACTIVE, active ? 1 : 0, 0);
+ // Need to send this message after the document regains focus.
+ if (active && mListBoxMessage != null) {
+ mWebViewCore.sendMessage(mListBoxMessage);
+ mListBoxMessage = null;
+ }
}
@Override
@@ -5015,14 +5059,15 @@
startTouch(detector.getFocusX(), detector.getFocusY(), mLastTouchTime);
}
+ // See if there is a layer at x, y and switch to TOUCH_DRAG_LAYER_MODE if a
+ // layer is found.
private void startScrollingLayer(float x, float y) {
- if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
- int contentX = viewToContentX((int) x + mScrollX);
- int contentY = viewToContentY((int) y + mScrollY);
- mScrollingLayer = nativeScrollableLayer(contentX, contentY);
- if (mScrollingLayer != 0) {
- mTouchMode = TOUCH_DRAG_LAYER_MODE;
- }
+ int contentX = viewToContentX((int) x + mScrollX);
+ int contentY = viewToContentY((int) y + mScrollY);
+ mScrollingLayer = nativeScrollableLayer(contentX, contentY,
+ mScrollingLayerRect);
+ if (mScrollingLayer != 0) {
+ mTouchMode = TOUCH_DRAG_LAYER_MODE;
}
}
@@ -5067,8 +5112,7 @@
final ScaleGestureDetector detector =
mZoomManager.getMultiTouchGestureDetector();
- if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1 &&
- mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+ if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) {
if (!detector.isInProgress() &&
ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
// Insert a fake pointer down event in order to start
@@ -5298,7 +5342,7 @@
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- int layer = nativeScrollableLayer(contentX, contentY);
+ int layer = nativeScrollableLayer(contentX, contentY, mScrollingLayerRect);
if (layer == 0) {
mAutoScrollX = x <= SELECT_SCROLL ? -SELECT_SCROLL
: x >= getViewWidth() - SELECT_SCROLL
@@ -5358,6 +5402,7 @@
deltaX = 0;
deltaY = 0;
+ startScrollingLayer(x, y);
startDrag();
}
@@ -5426,7 +5471,6 @@
mUserScroll = true;
}
- startScrollingLayer(x, y);
doDrag(deltaX, deltaY);
// Turn off scrollbars when dragging a layer.
@@ -5649,21 +5693,47 @@
private void doDrag(int deltaX, int deltaY) {
if ((deltaX | deltaY) != 0) {
- if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
- deltaX = viewToContentDimension(deltaX);
- deltaY = viewToContentDimension(deltaY);
- if (nativeScrollLayer(mScrollingLayer, deltaX, deltaY)) {
- invalidate();
- return;
- }
- // Switch to drag mode and fall through.
- mTouchMode = TOUCH_DRAG_MODE;
- }
+ int oldX = mScrollX;
+ int oldY = mScrollY;
+ int rangeX = computeMaxScrollX();
+ int rangeY = computeMaxScrollY();
+ int overscrollDistance = mOverscrollDistance;
- final int oldX = mScrollX;
- final int oldY = mScrollY;
- final int rangeX = computeMaxScrollX();
- final int rangeY = computeMaxScrollY();
+ // Check for the original scrolling layer in case we change
+ // directions. mTouchMode might be TOUCH_DRAG_MODE if we have
+ // reached the edge of a layer but mScrollingLayer will be non-zero
+ // if we initiated the drag on a layer.
+ if (mScrollingLayer != 0) {
+ final int contentX = viewToContentDimension(deltaX);
+ final int contentY = viewToContentDimension(deltaY);
+
+ // Check the scrolling bounds to see if we will actually do any
+ // scrolling. The rectangle is in document coordinates.
+ final int maxX = mScrollingLayerRect.right;
+ final int maxY = mScrollingLayerRect.bottom;
+ final int resultX = Math.max(0,
+ Math.min(mScrollingLayerRect.left + contentX, maxX));
+ final int resultY = Math.max(0,
+ Math.min(mScrollingLayerRect.top + contentY, maxY));
+
+ if (resultX != mScrollingLayerRect.left ||
+ resultY != mScrollingLayerRect.top) {
+ // In case we switched to dragging the page.
+ mTouchMode = TOUCH_DRAG_LAYER_MODE;
+ deltaX = contentX;
+ deltaY = contentY;
+ oldX = mScrollingLayerRect.left;
+ oldY = mScrollingLayerRect.top;
+ rangeX = maxX;
+ rangeY = maxY;
+ } else {
+ // Scroll the main page if we are not going to scroll the
+ // layer. This does not reset mScrollingLayer in case the
+ // user changes directions and the layer can scroll the
+ // other way.
+ mTouchMode = TOUCH_DRAG_MODE;
+ }
+ }
if (mOverScrollGlow != null) {
mOverScrollGlow.setOverScrollDeltas(deltaX, deltaY);
@@ -6062,6 +6132,21 @@
int vx = (int) mVelocityTracker.getXVelocity();
int vy = (int) mVelocityTracker.getYVelocity();
+ int scrollX = mScrollX;
+ int scrollY = mScrollY;
+ int overscrollDistance = mOverscrollDistance;
+ int overflingDistance = mOverflingDistance;
+
+ // Use the layer's scroll data if applicable.
+ if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+ scrollX = mScrollingLayerRect.left;
+ scrollY = mScrollingLayerRect.top;
+ maxX = mScrollingLayerRect.right;
+ maxY = mScrollingLayerRect.bottom;
+ // No overscrolling for layers.
+ overscrollDistance = overflingDistance = 0;
+ }
+
if (mSnapScrollMode != SNAP_NONE) {
if ((mSnapScrollMode & SNAP_X) == SNAP_X) {
vy = 0;
@@ -6079,8 +6164,7 @@
if (!mSelectingText) {
WebViewCore.resumeUpdatePicture(mWebViewCore);
}
- if (mScroller.springBack(mScrollX, mScrollY, 0, computeMaxScrollX(),
- 0, computeMaxScrollY())) {
+ if (mScroller.springBack(scrollX, scrollY, 0, maxX, 0, maxY)) {
invalidate();
}
return;
@@ -6107,24 +6191,25 @@
+ " current=" + currentVelocity
+ " vx=" + vx + " vy=" + vy
+ " maxX=" + maxX + " maxY=" + maxY
- + " mScrollX=" + mScrollX + " mScrollY=" + mScrollY);
+ + " scrollX=" + scrollX + " scrollY=" + scrollY
+ + " layer=" + mScrollingLayer);
}
// Allow sloppy flings without overscrolling at the edges.
- if ((mScrollX == 0 || mScrollX == maxX) && Math.abs(vx) < Math.abs(vy)) {
+ if ((scrollX == 0 || scrollX == maxX) && Math.abs(vx) < Math.abs(vy)) {
vx = 0;
}
- if ((mScrollY == 0 || mScrollY == maxY) && Math.abs(vy) < Math.abs(vx)) {
+ if ((scrollY == 0 || scrollY == maxY) && Math.abs(vy) < Math.abs(vx)) {
vy = 0;
}
- if (mOverscrollDistance < mOverflingDistance) {
- if ((vx > 0 && mScrollX == -mOverscrollDistance) ||
- (vx < 0 && mScrollX == maxX + mOverscrollDistance)) {
+ if (overscrollDistance < overflingDistance) {
+ if ((vx > 0 && scrollX == -overscrollDistance) ||
+ (vx < 0 && scrollX == maxX + overscrollDistance)) {
vx = 0;
}
- if ((vy > 0 && mScrollY == -mOverscrollDistance) ||
- (vy < 0 && mScrollY == maxY + mOverscrollDistance)) {
+ if ((vy > 0 && scrollY == -overscrollDistance) ||
+ (vy < 0 && scrollY == maxY + overscrollDistance)) {
vy = 0;
}
}
@@ -6134,8 +6219,8 @@
mLastVelocity = velocity;
// no horizontal overscroll if the content just fits
- mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY,
- maxX == 0 ? 0 : mOverflingDistance, mOverflingDistance);
+ mScroller.fling(scrollX, scrollY, -vx, -vy, 0, maxX, 0, maxY,
+ maxX == 0 ? 0 : overflingDistance, overflingDistance);
// Duration is calculated based on velocity. With range boundaries and overscroll
// we may not know how long the final animation will take. (Hence the deprecation
// warning on the call below.) It's not a big deal for scroll bars but if webcore
@@ -6505,6 +6590,9 @@
public boolean requestChildRectangleOnScreen(View child,
Rect rect,
boolean immediate) {
+ if (mNativeClass == 0) {
+ return false;
+ }
// don't scroll while in zoom animation. When it is done, we will adjust
// the necessary components (e.g., WebTextView if it is in editing mode)
if (mZoomManager.isFixedLengthAnimationInProgress()) {
@@ -6940,6 +7028,7 @@
mDeferTouchMode = TOUCH_DRAG_MODE;
mLastDeferTouchX = x;
mLastDeferTouchY = y;
+ startScrollingLayer(x, y);
startDrag();
}
int deltaX = pinLocX((int) (mScrollX
@@ -6948,7 +7037,6 @@
int deltaY = pinLocY((int) (mScrollY
+ mLastDeferTouchY - y))
- mScrollY;
- startScrollingLayer(x, y);
doDrag(deltaX, deltaY);
if (deltaX != 0) mLastDeferTouchX = x;
if (deltaY != 0) mLastDeferTouchY = y;
@@ -7429,8 +7517,10 @@
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v,
int position, long id) {
- mWebViewCore.sendMessage(
- EventHub.SINGLE_LISTBOX_CHOICE, (int)id, 0);
+ // Rather than sending the message right away, send it
+ // after the page regains focus.
+ mListBoxMessage = Message.obtain(null,
+ EventHub.SINGLE_LISTBOX_CHOICE, (int) id, 0);
mListBoxDialog.dismiss();
mListBoxDialog = null;
}
@@ -7455,6 +7545,8 @@
}
}
+ private Message mListBoxMessage;
+
/*
* Request a dropdown menu for a listbox with multiple selection.
*
@@ -7840,6 +7932,6 @@
native int nativeGetBlockLeftEdge(int x, int y, float scale);
// Returns a pointer to the scrollable LayerAndroid at the given point.
- private native int nativeScrollableLayer(int x, int y);
+ private native int nativeScrollableLayer(int x, int y, Rect scrollRect);
private native boolean nativeScrollLayer(int layer, int dx, int dy);
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index cc94fd0..d2c7fce 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -852,6 +852,7 @@
"VALID_NODE_BOUNDS", // = 146
"SAVE_WEBARCHIVE", // = 147
"WEBKIT_DRAW_LAYERS", // = 148;
+ "REMOVE_JS_INTERFACE", // = 149;
};
class EventHub {
@@ -925,6 +926,8 @@
// Update layers
static final int WEBKIT_DRAW_LAYERS = 148;
+ static final int REMOVE_JS_INTERFACE = 149;
+
// Network-based messaging
static final int CLEAR_SSL_PREF_TABLE = 150;
@@ -1290,6 +1293,12 @@
jsData.mInterfaceName);
break;
+ case REMOVE_JS_INTERFACE:
+ jsData = (JSInterfaceData) msg.obj;
+ mBrowserFrame.removeJavascriptInterface(
+ jsData.mInterfaceName);
+ break;
+
case REQUEST_EXT_REPRESENTATION:
mBrowserFrame.externalRepresentation(
(Message) msg.obj);
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index b94dc3b..230cc51 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -580,7 +580,7 @@
mInvZoomOverviewWidth = 1.0f / width;
}
- private float getZoomOverviewScale() {
+ /* package */ float getZoomOverviewScale() {
return mWebView.getViewWidth() * mInvZoomOverviewWidth;
}
@@ -672,7 +672,10 @@
}
public boolean onScale(ScaleGestureDetector detector) {
- float scale = Math.round(detector.getScaleFactor() * mActualScale * 100) * 0.01f;
+ // Prevent scaling beyond overview scale.
+ float scale = Math.max(
+ Math.round(detector.getScaleFactor() * mActualScale * 100) * 0.01f,
+ getZoomOverviewScale());
if (willScaleTriggerZoom(scale)) {
mPinchToZoomAnimating = true;
// limit the scale change per step
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 595b487..261992b 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,6 +16,8 @@
package android.widget;
+import com.android.internal.R;
+
import android.annotation.Widget;
import android.content.Context;
import android.content.res.TypedArray;
@@ -26,50 +28,44 @@
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.LayoutInflater;
-import android.widget.NumberPicker;
import android.widget.NumberPicker.OnChangedListener;
-import com.android.internal.R;
-
-import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
/**
* A view for selecting a month / year / day based on a calendar like layout.
- *
- * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker
- * tutorial</a>.</p>
- *
+ * <p>
+ * See the <a href="{@docRoot}
+ * resources/tutorials/views/hello-datepicker.html">Date Picker tutorial</a>.
+ * </p>
* For a dialog using this view, see {@link android.app.DatePickerDialog}.
*/
@Widget
public class DatePicker extends FrameLayout {
private static final int DEFAULT_START_YEAR = 1900;
+
private static final int DEFAULT_END_YEAR = 2100;
- // This ignores Undecimber, but we only support real Gregorian calendars.
- private static final int NUMBER_OF_MONTHS = 12;
-
- /* UI Components */
private final NumberPicker mDayPicker;
+
private final NumberPicker mMonthPicker;
+
private final NumberPicker mYearPicker;
- /**
- * How we notify users the date has changed.
- */
- private OnDateChangedListener mOnDateChangedListener;
-
- private int mDay;
- private int mMonth;
- private int mYear;
+ private final DayPicker mMiniMonthDayPicker;
- private Object mMonthUpdateLock = new Object();
- private volatile Locale mMonthLocale;
- private String[] mShortMonths;
+ private OnDateChangedListener mOnDateChangedListener;
+
+ private Locale mMonthLocale;
+
+ private final Calendar mTempCalendar = Calendar.getInstance();
+
+ private final int mNumberOfMonths = mTempCalendar.getActualMaximum(Calendar.MONTH) + 1;
+
+ private final String[] mShortMonths = new String[mNumberOfMonths];
/**
* The callback used to indicate the user changes the date.
@@ -80,7 +76,7 @@
* @param view The view associated with this listener.
* @param year The year that was set.
* @param monthOfYear The month that was set (0-11) for compatibility
- * with {@link java.util.Calendar}.
+ * with {@link java.util.Calendar}.
* @param dayOfMonth The day of the month that was set.
*/
void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
@@ -89,7 +85,7 @@
public DatePicker(Context context) {
this(context, null);
}
-
+
public DatePicker(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -97,103 +93,85 @@
public DatePicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.date_picker, this, true);
+ OnChangedListener onChangeListener = new OnChangedListener() {
+ public void onChanged(NumberPicker picker, int oldVal, int newVal) {
+ notifyDateChanged();
+ updateMiniMonth();
+ }
+ };
+
+ // day
mDayPicker = (NumberPicker) findViewById(R.id.day);
mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
mDayPicker.setSpeed(100);
- mDayPicker.setOnChangeListener(new OnChangedListener() {
- public void onChanged(NumberPicker picker, int oldVal, int newVal) {
- mDay = newVal;
- notifyDateChanged();
- }
- });
+ mDayPicker.setOnChangeListener(onChangeListener);
+
+ // month
mMonthPicker = (NumberPicker) findViewById(R.id.month);
- mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
- final String[] months = getShortMonths();
-
- /*
- * If the user is in a locale where the month names are numeric,
- * use just the number instead of the "month" character for
- * consistency with the other fields.
- */
- if (months[0].startsWith("1")) {
- for (int i = 0; i < months.length; i++) {
- months[i] = String.valueOf(i + 1);
- }
- mMonthPicker.setRange(1, NUMBER_OF_MONTHS);
- } else {
- mMonthPicker.setRange(1, NUMBER_OF_MONTHS, months);
- }
-
+ mMonthPicker.setRange(0, mNumberOfMonths - 1, getShortMonths());
mMonthPicker.setSpeed(200);
- mMonthPicker.setOnChangeListener(new OnChangedListener() {
- public void onChanged(NumberPicker picker, int oldVal, int newVal) {
-
- /* We display the month 1-12 but store it 0-11 so always
- * subtract by one to ensure our internal state is always 0-11
- */
- mMonth = newVal - 1;
- // Adjust max day of the month
- adjustMaxDay();
- notifyDateChanged();
- updateDaySpinner();
- }
- });
+ mMonthPicker.setOnChangeListener(onChangeListener);
+
+ // year
mYearPicker = (NumberPicker) findViewById(R.id.year);
mYearPicker.setSpeed(100);
- mYearPicker.setOnChangeListener(new OnChangedListener() {
- public void onChanged(NumberPicker picker, int oldVal, int newVal) {
- mYear = newVal;
- // Adjust max day for leap years if needed
- adjustMaxDay();
- notifyDateChanged();
- updateDaySpinner();
- }
- });
-
- // attributes
+ mYearPicker.setOnChangeListener(onChangeListener);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
-
int mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
int mEndYear = a.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
mYearPicker.setRange(mStartYear, mEndYear);
-
a.recycle();
+
+ // mini-month day-picker
+ mMiniMonthDayPicker = (DayPicker) findViewById(R.id.mini_month_day_picker);
+ mTempCalendar.clear();
+ mTempCalendar.set(mStartYear, 0, 1);
+ Calendar endRangeDate = (Calendar) mTempCalendar.clone();
+ endRangeDate.set(mEndYear, 11, 31);
+ mMiniMonthDayPicker.setRange(mTempCalendar, endRangeDate);
+ mMiniMonthDayPicker.setOnDateChangeListener(new DayPicker.OnSelectedDayChangeListener() {
+ public void onSelectedDayChange(DayPicker view, int year, int month, int monthDay) {
+ updateDate(year, month, monthDay);
+ }
+ });
// initialize to current date
- Calendar cal = Calendar.getInstance();
- init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
-
+ mTempCalendar.setTimeInMillis(System.currentTimeMillis());
+ init(mTempCalendar.get(Calendar.YEAR), mTempCalendar.get(Calendar.MONTH),
+ mTempCalendar.get(Calendar.DAY_OF_MONTH), null);
+
// re-order the number pickers to match the current date format
- reorderPickers(months);
-
- if (!isEnabled()) {
- setEnabled(false);
- }
+ reorderPickers();
}
-
+
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
mDayPicker.setEnabled(enabled);
mMonthPicker.setEnabled(enabled);
mYearPicker.setEnabled(enabled);
+ mMiniMonthDayPicker.setEnabled(enabled);
}
- private void reorderPickers(String[] months) {
+ /**
+ * Reorders the pickers according to the date format in the current locale.
+ */
+ private void reorderPickers() {
java.text.DateFormat format;
String order;
/*
- * If the user is in a locale where the medium date format is
- * still numeric (Japanese and Czech, for example), respect
- * the date format order setting. Otherwise, use the order
- * that the locale says is appropriate for a spelled-out date.
+ * If the user is in a locale where the medium date format is still
+ * numeric (Japanese and Czech, for example), respect the date format
+ * order setting. Otherwise, use the order that the locale says is
+ * appropriate for a spelled-out date.
*/
- if (months[0].startsWith("1")) {
+ if (getShortMonths()[0].startsWith("1")) {
format = DateFormat.getDateFormat(getContext());
} else {
format = DateFormat.getMediumDateFormat(getContext());
@@ -206,10 +184,11 @@
order = new String(DateFormat.getDateFormatOrder(getContext()));
}
- /* Remove the 3 pickers from their parent and then add them back in the
+ /*
+ * Remove the 3 pickers from their parent and then add them back in the
* required order.
*/
- LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
+ LinearLayout parent = (LinearLayout) findViewById(R.id.pickers);
parent.removeAllViews();
boolean quoted = false;
@@ -230,7 +209,7 @@
parent.addView(mMonthPicker);
didMonth = true;
} else if (c == DateFormat.YEAR && !didYear) {
- parent.addView (mYearPicker);
+ parent.addView(mYearPicker);
didYear = true;
}
}
@@ -248,40 +227,145 @@
}
}
- public void updateDate(int year, int monthOfYear, int dayOfMonth) {
- if (mYear != year || mMonth != monthOfYear || mDay != dayOfMonth) {
- mYear = year;
- mMonth = monthOfYear;
- mDay = dayOfMonth;
- updateSpinners();
- reorderPickers(getShortMonths());
+ /**
+ * Updates the current date.
+ *
+ * @param year The year.
+ * @param month The month which is <strong>starting from zero</strong>.
+ * @param dayOfMonth The day of the month.
+ */
+ public void updateDate(int year, int month, int dayOfMonth) {
+ if (mYearPicker.getCurrent() != year
+ || mDayPicker.getCurrent() != dayOfMonth
+ || mMonthPicker.getCurrent() != month) {
+ updatePickers(year, month, dayOfMonth);
+ updateMiniMonth();
notifyDateChanged();
}
}
+ /**
+ * @return The short month abbreviations.
+ */
private String[] getShortMonths() {
final Locale currentLocale = Locale.getDefault();
- if (currentLocale.equals(mMonthLocale) && mShortMonths != null) {
+ if (currentLocale.equals(mMonthLocale)) {
return mShortMonths;
} else {
- synchronized (mMonthUpdateLock) {
- if (!currentLocale.equals(mMonthLocale)) {
- mShortMonths = new String[NUMBER_OF_MONTHS];
- for (int i = 0; i < NUMBER_OF_MONTHS; i++) {
- mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
- DateUtils.LENGTH_MEDIUM);
- }
- mMonthLocale = currentLocale;
- }
+ for (int i = 0; i < mNumberOfMonths; i++) {
+ mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
+ DateUtils.LENGTH_MEDIUM);
}
+ mMonthLocale = currentLocale;
return mShortMonths;
}
}
+ // Override so we are in complete control of save / restore for this widget.
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+ dispatchThawSelfOnly(container);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+ return new SavedState(superState, mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
+ mDayPicker.getCurrent());
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ updatePickers(ss.mYear, ss.mMonth, ss.mDay);
+ }
+
+ /**
+ * Initialize the state. If the provided values designate an inconsistent
+ * date the values are normalized before updating the pickers.
+ *
+ * @param year The initial year.
+ * @param monthOfYear The initial month <strong>starting from zero</strong>.
+ * @param dayOfMonth The initial day of the month.
+ * @param onDateChangedListener How user is notified date is changed by
+ * user, can be null.
+ */
+ public void init(int year, int monthOfYear, int dayOfMonth,
+ OnDateChangedListener onDateChangedListener) {
+ mOnDateChangedListener = onDateChangedListener;
+ updateDate(year, monthOfYear, dayOfMonth);
+ }
+
+ /**
+ * Updates the pickers with the given <code>year</code>, <code>month</code>,
+ * and <code>dayOfMonth</code>. If the provided values designate an inconsistent
+ * date the values are normalized before updating the pickers.
+ */
+ private void updatePickers(int year, int month, int dayOfMonth) {
+ // make sure the date is normalized
+ mTempCalendar.clear();
+ mTempCalendar.set(year, month, dayOfMonth);
+ mYearPicker.setCurrent(mTempCalendar.get(Calendar.YEAR));
+ mMonthPicker.setCurrent(mTempCalendar.get(Calendar.MONTH));
+ mDayPicker.setRange(1, mTempCalendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+ mDayPicker.setCurrent(mTempCalendar.get(Calendar.DAY_OF_MONTH));
+ }
+
+ /**
+ * Updates the mini-month with the given year, month, and day selected by the
+ * number pickers.
+ */
+ private void updateMiniMonth() {
+ Calendar selectedDay = mMiniMonthDayPicker.getSelectedDay();
+ if (selectedDay.get(Calendar.YEAR) != mYearPicker.getCurrent()
+ || selectedDay.get(Calendar.MONTH) != mMonthPicker.getCurrent()
+ || selectedDay.get(Calendar.DAY_OF_MONTH) != mDayPicker.getCurrent()) {
+ mMiniMonthDayPicker.goTo(mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
+ mDayPicker.getCurrent(), false, true, false);
+ }
+ }
+
+ /**
+ * @return The selected year.
+ */
+ public int getYear() {
+ return mYearPicker.getCurrent();
+ }
+
+ /**
+ * @return The selected month.
+ */
+ public int getMonth() {
+ return mMonthPicker.getCurrent();
+ }
+
+ /**
+ * @return The selected day of month.
+ */
+ public int getDayOfMonth() {
+ return mDayPicker.getCurrent();
+ }
+
+ /**
+ * Notifies the listener, if such, for a change in the selected date.
+ */
+ private void notifyDateChanged() {
+ if (mOnDateChangedListener != null) {
+ mOnDateChangedListener.onDateChanged(DatePicker.this, mYearPicker.getCurrent(),
+ mMonthPicker.getCurrent(), mDayPicker.getCurrent());
+ }
+ }
+
+ /**
+ * Class for managing state storing/restoring.
+ */
private static class SavedState extends BaseSavedState {
private final int mYear;
+
private final int mMonth;
+
private final int mDay;
/**
@@ -293,7 +377,7 @@
mMonth = month;
mDay = day;
}
-
+
/**
* Constructor called from {@link #CREATOR}
*/
@@ -304,18 +388,6 @@
mDay = in.readInt();
}
- public int getYear() {
- return mYear;
- }
-
- public int getMonth() {
- return mMonth;
- }
-
- public int getDay() {
- return mDay;
- }
-
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
@@ -324,104 +396,17 @@
dest.writeInt(mDay);
}
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Creator<SavedState>() {
+ @SuppressWarnings("all")
+ // suppress unused and hiding
+ public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
-
- /**
- * Override so we are in complete control of save / restore for this widget.
- */
- @Override
- protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
- dispatchThawSelfOnly(container);
- }
-
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
-
- return new SavedState(superState, mYear, mMonth, mDay);
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
- mYear = ss.getYear();
- mMonth = ss.getMonth();
- mDay = ss.getDay();
- updateSpinners();
- }
-
- /**
- * Initialize the state.
- * @param year The initial year.
- * @param monthOfYear The initial month.
- * @param dayOfMonth The initial day of the month.
- * @param onDateChangedListener How user is notified date is changed by user, can be null.
- */
- public void init(int year, int monthOfYear, int dayOfMonth,
- OnDateChangedListener onDateChangedListener) {
- mYear = year;
- mMonth = monthOfYear;
- mDay = dayOfMonth;
- mOnDateChangedListener = onDateChangedListener;
- updateSpinners();
- }
-
- private void updateSpinners() {
- updateDaySpinner();
- mYearPicker.setCurrent(mYear);
-
- /* The month display uses 1-12 but our internal state stores it
- * 0-11 so add one when setting the display.
- */
- mMonthPicker.setCurrent(mMonth + 1);
- }
-
- private void updateDaySpinner() {
- Calendar cal = Calendar.getInstance();
- cal.set(mYear, mMonth, mDay);
- int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
- mDayPicker.setRange(1, max);
- mDayPicker.setCurrent(mDay);
- }
-
- public int getYear() {
- return mYear;
- }
-
- public int getMonth() {
- return mMonth;
- }
-
- public int getDayOfMonth() {
- return mDay;
- }
-
- private void adjustMaxDay(){
- Calendar cal = Calendar.getInstance();
- cal.set(Calendar.YEAR, mYear);
- cal.set(Calendar.MONTH, mMonth);
- int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
- if (mDay > max) {
- mDay = max;
- }
- }
-
- private void notifyDateChanged() {
- if (mOnDateChangedListener != null) {
- mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay);
- }
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
}
}
diff --git a/core/java/android/widget/DayPicker.java b/core/java/android/widget/DayPicker.java
new file mode 100644
index 0000000..11c23ab
--- /dev/null
+++ b/core/java/android/widget/DayPicker.java
@@ -0,0 +1,1474 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import com.android.internal.R;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.text.format.Time;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView.OnScrollListener;
+
+import java.security.InvalidParameterException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Locale;
+
+import libcore.icu.LocaleData;
+
+/**
+ * Displays a day picker in the form of a calendar. The calendar
+ * is represented as a list where each row depicts a week. Each week is
+ * composed of items that are selectable days.
+ */
+public class DayPicker extends FrameLayout {
+
+ /**
+ * The number of milliseconds in a day.
+ *
+ * @hide
+ */
+ protected static final long MILLIS_IN_DAY = 86400000L;
+
+ /**
+ * The number of day in a week.
+ *
+ * @hide
+ */
+ protected static final int DAYS_PER_WEEK = 7;
+
+ /**
+ * The number of milliseconds in a week.
+ *
+ * @hide
+ */
+ protected static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY;
+
+ /**
+ * Affects when the month selection will change while scrolling up
+ *
+ * @hide
+ */
+ protected static final int SCROLL_HYST_WEEKS = 2;
+
+ /**
+ * How long the GoTo fling animation should last.
+ *
+ * @hide
+ */
+ protected static final int GOTO_SCROLL_DURATION = 1000;
+
+ /**
+ * The duration of the adjustment upon a user scroll in milliseconds.
+ *
+ * @hide
+ */
+ protected static final int ADJUSTMENT_SCROLL_DURATION = 500;
+
+ /**
+ * How long to wait after receiving an onScrollStateChanged notification
+ * before acting on it.
+ *
+ * @hide
+ */
+ protected static final int SCROLL_CHANGE_DELAY = 40;
+
+ /**
+ * The scale used to compensate for different screen density.
+ *
+ * @hide
+ */
+ protected static float sScale;
+
+ /**
+ * The top offset of the weeks list.
+ *
+ * @hide
+ */
+ protected static int mListTopOffset = 2;
+
+ /**
+ * The visible height of a week view.
+ *
+ * @hide
+ */
+ protected int mWeekMinVisibleHeight = 12;
+
+
+ /**
+ * The visible height of a week view.
+ *
+ * @hide
+ */
+ protected int mBottomBuffer = 20;
+
+ /**
+ * The number of shown weeks.
+ *
+ * @hide
+ */
+ protected int mShownWeekCount = 6;
+
+ /**
+ * Flag whether to show the week number.
+ *
+ * @hide
+ */
+ protected boolean mShowWeekNumber = true;
+
+ /**
+ * The number of day per week to be shown
+ *
+ * @hide
+ */
+ protected int mDaysPerWeek = 7;
+
+ /**
+ * The friction of the week list while flinging.
+ *
+ * @hide
+ */
+ protected float mFriction = .05f;
+
+ /**
+ * Scale for adjusting velocity of the week list while flinging.
+ *
+ * @hide
+ */
+ protected float mVelocityScale = 0.333f;
+
+ /**
+ * The adapter for the weeks list.
+ *
+ * @hide
+ */
+ protected WeeksAdapter mAdapter;
+
+ /**
+ * The weeks list.
+ *
+ * @hide
+ */
+ protected ListView mListView;
+
+ /**
+ * The name of the month to display.
+ *
+ * @hide
+ */
+ protected TextView mMonthName;
+
+ /**
+ * The header with week day names.
+ *
+ * @hide
+ */
+ protected ViewGroup mDayNamesHeader;
+
+ /**
+ * Cached labels for the week names header.
+ *
+ * @hide
+ */
+ protected String[] mDayLabels;
+
+ /**
+ * Temporary instance to avoid multiple instantiations.
+ *
+ * @hide
+ */
+ protected Calendar mTempCalendar = Calendar.getInstance();
+
+ /**
+ * The first day of the week based on the current locale.
+ *
+ * @hide
+ */
+ protected int mFirstDayOfWeek = LocaleData.get(Locale.getDefault()).firstDayOfWeek;
+
+ /**
+ * The first day of the focused month.
+ *
+ * @hide
+ */
+ protected Calendar mFirstDayOfMonth = Calendar.getInstance();
+
+ /**
+ * Which month should be displayed/highlighted [0-11]
+ *
+ * @hide
+ */
+ protected int mCurrentMonthDisplayed;
+
+ /**
+ * Used for tracking during a scroll.
+ *
+ * @hide
+ */
+ protected long mPreviousScrollPosition;
+
+ /**
+ * Used for tracking which direction the view is scrolling.
+ *
+ * @hide
+ */
+ protected boolean mIsScrollingUp = false;
+
+ /**
+ * The previous scroll state of the weeks ListView.
+ *
+ * @hide
+ */
+ protected int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+ /**
+ * The current scroll state of the weeks ListView.
+ *
+ * @hide
+ */
+ protected int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+ /**
+ * Listener for changes in the selected day.
+ *
+ * @hide
+ */
+ protected OnSelectedDayChangeListener mOnChangeListener;
+
+ /**
+ * Command for adjusting the position after a scroll/fling.
+ *
+ * @hide
+ */
+ protected ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
+
+ /**
+ * The start date of the range supported by this picker.
+ *
+ * @hide
+ */
+ protected Calendar mStartRangeDate = Calendar.getInstance();
+
+ /**
+ * The end date of the range supported by this picker.
+ *
+ * @hide
+ */
+ protected Calendar mEndRangeDate = Calendar.getInstance();
+
+ /**
+ * String for formatting the month name in the title text view.
+ *
+ * @hide
+ */
+ protected String mMonthNameFormatSrting = "MMMM, yyyy";
+
+ /**
+ * The callback used to indicate the user changes the date.
+ */
+ public interface OnSelectedDayChangeListener {
+
+ /**
+ * Called upon change of the selected day.
+ *
+ * @param view The view associated with this listener.
+ * @param year The year that was set.
+ * @param month The month that was set [0-11].
+ * @param dayOfMonth The day of the month that was set.
+ */
+ public void onSelectedDayChange(DayPicker view, int year, int month, int dayOfMonth);
+ }
+
+ public DayPicker(Context context) {
+ this(context, null);
+ }
+
+ public DayPicker(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public DayPicker(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, 0);
+
+ LayoutInflater layoutInflater = (LayoutInflater) mContext
+ .getSystemService(Service.LAYOUT_INFLATER_SERVICE);
+ View content = layoutInflater.inflate(R.layout.day_picker, null, false);
+ addView(content);
+
+ mListView = (ListView) findViewById(R.id.list);
+ mDayNamesHeader = (ViewGroup) content.findViewById(com.android.internal.R.id.day_names);
+ mMonthName = (TextView) content.findViewById(com.android.internal.R.id.month_name);
+
+ // Adjust sizes for screen density
+ if (sScale == 0) {
+ sScale = mContext.getResources().getDisplayMetrics().density;
+ if (sScale != 1) {
+ mWeekMinVisibleHeight *= sScale;
+ mBottomBuffer *= sScale;
+ mListTopOffset *= sScale;
+ }
+ }
+
+ // set default range
+ mStartRangeDate.clear();
+ mStartRangeDate.set(1900, 0, 1);
+ mEndRangeDate.clear();
+ mEndRangeDate.set(2100, 0, 1);
+
+ setUpHeader();
+ updateHeader();
+ setUpListView();
+ setUpAdapter();
+
+ // go to today now
+ mTempCalendar.setTimeInMillis(System.currentTimeMillis());
+ goTo(mTempCalendar, false, true, true);
+ invalidate();
+ }
+
+ /**
+ * Sets the range supported by this day picker. This is the picker will not
+ * support dates before <code>startRangeDate</code> and <code>endRangeDate
+ * </code>.
+ *
+ * @param startRangeDate The start date.
+ * @param endRangeDate The end date.
+ */
+ public void setRange(Calendar startRangeDate, Calendar endRangeDate) {
+ boolean doSetupAdapter = false;
+ if (mStartRangeDate.get(Calendar.DAY_OF_YEAR) != startRangeDate.get(Calendar.DAY_OF_YEAR)
+ || mStartRangeDate.get(Calendar.YEAR) != startRangeDate.get(Calendar.YEAR)) {
+ mStartRangeDate = startRangeDate;
+ doSetupAdapter = true;
+ }
+ if (mEndRangeDate.get(Calendar.DAY_OF_YEAR) != endRangeDate.get(Calendar.DAY_OF_YEAR)
+ || mEndRangeDate.get(Calendar.YEAR) != endRangeDate.get(Calendar.YEAR)) {
+ mEndRangeDate = endRangeDate;
+ doSetupAdapter = true;
+
+ }
+ if (doSetupAdapter) {
+ setUpAdapter();
+ }
+ }
+
+ /**
+ * Sets the listener to be notified upon day selection changes.
+ *
+ * @param listener The listener to be called back.
+ */
+ public void setOnDateChangeListener(OnSelectedDayChangeListener listener) {
+ mOnChangeListener = listener;
+ }
+
+ /**
+ * Gets the selected day.
+ *
+ * @return The selected day.
+ */
+ public Calendar getSelectedDay() {
+ return mAdapter.mSelectedDay;
+ }
+
+ /**
+ * Sets the selected day. This is equivalent to a call to
+ * {@link #goTo(Calendar, boolean, boolean, boolean)} with
+ * the arguments <code>selectedDay</code>, <code>false</code>,
+ * <code>true</code>, <code>false</code> respectively.
+ *
+ * @param selectedDay The selected day.
+ */
+ public void setSelectedDay(Calendar selectedDay) {
+ goTo(selectedDay, false, true, false);
+ }
+
+ /**
+ * Creates a new adapter if necessary and sets up its parameters. Override
+ * this method to provide a custom adapter.
+ *
+ * @hide
+ */
+ protected void setUpAdapter() {
+ if (mAdapter == null) {
+ mAdapter = new WeeksAdapter(getContext());
+ mAdapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ if (mOnChangeListener != null) {
+ Calendar selectedDay = mAdapter.getSelectedDay();
+ mOnChangeListener.onSelectedDayChange(DayPicker.this,
+ selectedDay.get(Calendar.YEAR),
+ selectedDay.get(Calendar.MONTH),
+ selectedDay.get(Calendar.DAY_OF_MONTH));
+ }
+ }
+ });
+ mListView.setAdapter(mAdapter);
+ }
+
+ // refresh the view with the new parameters
+ mAdapter.notifyDataSetChanged();
+ }
+
+ /**
+ * Sets up the strings to be used by the header. Override this method to use
+ * different strings or modify the view params.
+ *
+ * @hide
+ */
+ protected void setUpHeader() {
+ mDayLabels = new String[mDaysPerWeek];
+ for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
+ int calendarDay = (i < mDaysPerWeek) ? i : 1; // Calendar.MONDAY is
+ // 1
+ mDayLabels[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
+ DateUtils.LENGTH_SHORTEST);
+ }
+ }
+
+ /**
+ * Sets all the required fields for the list view. Override this method to
+ * set a different list view behavior.
+ *
+ * @hide
+ */
+ protected void setUpListView() {
+ // Configure the listview
+ mListView.setDivider(null);
+ mListView.setItemsCanFocus(true);
+ mListView.setVerticalScrollBarEnabled(false);
+ mListView.setOnScrollListener(new OnScrollListener() {
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ DayPicker.this.onScrollStateChanged(view, scrollState);
+ }
+
+ public void onScroll(
+ AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ DayPicker.this.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
+ }
+ });
+ // Make the scrolling behavior nicer
+ mListView.setFriction(mFriction);
+ mListView.setVelocityScale(mVelocityScale);
+ }
+
+ /**
+ * Fixes the day names header to provide correct spacing and updates the
+ * label text. Override this to set up a custom header.
+ *
+ * @hide
+ */
+ protected void updateHeader() {
+ TextView label = (TextView) mDayNamesHeader.getChildAt(0);
+ if (mShowWeekNumber) {
+ label.setVisibility(View.VISIBLE);
+ } else {
+ label.setVisibility(View.GONE);
+ }
+ for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
+ label = (TextView) mDayNamesHeader.getChildAt(i);
+ if (i < mDaysPerWeek + 1) {
+ label.setText(mDayLabels[i - 1]);
+ label.setVisibility(View.VISIBLE);
+ } else {
+ label.setVisibility(View.GONE);
+ }
+ }
+ mDayNamesHeader.invalidate();
+ }
+
+ /**
+ * This moves to the specified time in the view. If the time is not already
+ * in range it will move the list so that the first of the month containing
+ * the time is at the top of the view. If the new time is already in view
+ * the list will not be scrolled unless forceScroll is true. This time may
+ * optionally be highlighted as selected as well.
+ *
+ * @param year The year to move to.
+ * @param month The month to move to <strong>starting from zero<strong>.
+ * @param dayOfMonth The month day to move to.
+ * @param animate Whether to scroll to the given time or just redraw at the
+ * new location.
+ * @param setSelected Whether to set the given time as selected
+ * @param forceScroll Whether to recenter even if the time is already
+ * visible.
+ */
+ public void goTo(int year, int month, int dayOfMonth, boolean animate, boolean setSelected,
+ boolean forceScroll) {
+ mTempCalendar.clear();
+ mTempCalendar.set(year, month, dayOfMonth);
+ goTo(mTempCalendar, animate, setSelected, forceScroll);
+ }
+
+ /**
+ * This moves to the specified time in the view. If the time is not already
+ * in range it will move the list so that the first of the month containing
+ * the time is at the top of the view. If the new time is already in view
+ * the list will not be scrolled unless forceScroll is true. This time may
+ * optionally be highlighted as selected as well.
+ *
+ * @param date The time to move to.
+ * @param animate Whether to scroll to the given time or just redraw at the
+ * new location.
+ * @param setSelected Whether to set the given time as selected.
+ * @param forceScroll Whether to recenter even if the time is already
+ * visible.
+ */
+ public void goTo(Calendar date, boolean animate, boolean setSelected, boolean forceScroll) {
+ long timeInMillis = date.getTimeInMillis();
+ if (timeInMillis < mStartRangeDate.getTimeInMillis()
+ || timeInMillis > mEndRangeDate.getTimeInMillis()) {
+ throw new IllegalArgumentException("Time not between " + mStartRangeDate.getTime()
+ + " and " + mEndRangeDate.getTime());
+ }
+ // Find the first and last entirely visible weeks
+ int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
+ View firstChild = mListView.getChildAt(0);
+ if (firstChild != null && firstChild.getTop() < 0) {
+ firstFullyVisiblePosition++;
+ }
+ int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1;
+ if (firstChild != null && firstChild.getTop() > mBottomBuffer) {
+ lastFullyVisiblePosition--;
+ }
+ if (setSelected) {
+ mAdapter.setSelectedDay(date);
+ }
+ // Get the week we're going to
+ int position = getWeeksDelta(date);
+
+ // Check if the selected day is now outside of our visible range
+ // and if so scroll to the month that contains it
+ if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition
+ || forceScroll) {
+ mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis());
+ mFirstDayOfMonth.setTimeZone(date.getTimeZone());
+ mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
+
+ setMonthDisplayed(mFirstDayOfMonth);
+ position = getWeeksDelta(mFirstDayOfMonth);
+
+ mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
+ if (animate) {
+ mListView.smoothScrollToPositionFromTop(position, mListTopOffset,
+ GOTO_SCROLL_DURATION);
+ } else {
+ mListView.setSelectionFromTop(position, mListTopOffset);
+ // Perform any after scroll operations that are needed
+ onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE);
+ }
+ } else if (setSelected) {
+ // Otherwise just set the selection
+ setMonthDisplayed(date);
+ }
+ }
+
+ /**
+ * Called when a <code>view</code> transitions to a new <code>scrollState
+ * </code>.
+ *
+ * @hide
+ */
+ protected void onScrollStateChanged(AbsListView view, int scrollState) {
+ mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
+ }
+
+ /**
+ * Updates the title and selected month if the <code>view</code> has moved to a new
+ * month.
+ *
+ * @hide
+ */
+ protected void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ WeekView child = (WeekView) view.getChildAt(0);
+ if (child == null) {
+ return;
+ }
+
+ // Figure out where we are
+ int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0;
+ long currScroll = view.getFirstVisiblePosition() * child.getHeight() - child.getBottom();
+
+ // If we have moved since our last call update the direction
+ if (currScroll < mPreviousScrollPosition) {
+ mIsScrollingUp = true;
+ } else if (currScroll > mPreviousScrollPosition) {
+ mIsScrollingUp = false;
+ } else {
+ return;
+ }
+
+ // Use some hysteresis for checking which month to highlight. This
+ // causes the month to transition when two full weeks of a month are
+ // visible when scrolling up, and when the first day in a month reaches
+ // the top of the screen when scrolling down.
+ if (mIsScrollingUp) {
+ child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset);
+ } else if (offset != 0) {
+ child = (WeekView) view.getChildAt(offset);
+ }
+
+ // Find out which month we're moving into
+ int month;
+ if (mIsScrollingUp) {
+ month = child.getMonthOfFirstWeekDay();
+ } else {
+ month = child.getMonthOfLastWeekDay();
+ }
+
+ // And how it relates to our current highlighted month
+ int monthDiff;
+ if (mCurrentMonthDisplayed == 11 && month == 0) {
+ monthDiff = 1;
+ } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+ monthDiff = -1;
+ } else {
+ monthDiff = month - mCurrentMonthDisplayed;
+ }
+
+ // Only switch months if we're scrolling away from the currently
+ // selected month
+ if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
+ Calendar firstDay = child.getFirstDay();
+ if (mIsScrollingUp) {
+ firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+ } else {
+ firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+ }
+ setMonthDisplayed(firstDay);
+ }
+ mPreviousScrollPosition = currScroll;
+ mPreviousScrollState = mCurrentScrollState;
+ }
+
+ /**
+ * Sets the month displayed at the top of this view based on time. Override
+ * to add custom events when the title is changed.
+ *
+ * @param calendar A day in the new focus month.
+ *
+ * @hide
+ */
+ protected void setMonthDisplayed(Calendar calendar) {
+ mMonthName.setText(DateFormat.format(mMonthNameFormatSrting, calendar));
+ mMonthName.invalidate();
+ mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
+ mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+ // TODO Send Accessibility Event
+ }
+
+ /**
+ * @return Returns the number of weeks between the current week day of the
+ * <code>fromDate</code> and the first day of week of
+ * <code>toDate</code>.
+ *
+ * @hide
+ */
+ protected int getWeeksDelta(Calendar toDate) {
+ if (toDate.before(mStartRangeDate)) {
+ throw new IllegalArgumentException("fromDate: " + mStartRangeDate.getTime()
+ + " does not precede toDate: " + toDate.getTime());
+ }
+ int fromDateDayOfWeek = mStartRangeDate.get(Calendar.DAY_OF_WEEK);
+ long diff = (fromDateDayOfWeek - toDate.getFirstDayOfWeek()) * MILLIS_IN_DAY;
+ if (diff < 0) {
+ diff = diff + MILLIS_IN_WEEK;
+ }
+ long refDay = mStartRangeDate.getTimeInMillis() - diff;
+ return (int) ((toDate.getTimeInMillis() - refDay) / MILLIS_IN_WEEK);
+ }
+
+ /**
+ * Command responsible for acting upon scroll state changes.
+ *
+ * @hide
+ */
+ protected class ScrollStateRunnable implements Runnable {
+ private AbsListView mView;
+
+ private int mNewState;
+
+ /**
+ * Sets up the runnable with a short delay in case the scroll state
+ * immediately changes again.
+ *
+ * @param view The list view that changed state
+ * @param scrollState The new state it changed to
+ */
+ public void doScrollStateChange(AbsListView view, int scrollState) {
+ removeCallbacks(this);
+ mView = view;
+ mNewState = scrollState;
+ removeCallbacks(this);
+ postDelayed(this, SCROLL_CHANGE_DELAY);
+ }
+
+ public void run() {
+ mCurrentScrollState = mNewState;
+ // Fix the position after a scroll or a fling ends
+ if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
+ && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+ mPreviousScrollState = mNewState;
+ View child = mView.getChildAt(0);
+ if (child == null) {
+ // The view is no longer visible, just return
+ return;
+ }
+ int dist = child.getBottom() - mListTopOffset;
+ if (dist > mListTopOffset) {
+ if (mIsScrollingUp) {
+ mView.smoothScrollBy(dist - child.getHeight(), ADJUSTMENT_SCROLL_DURATION);
+ } else {
+ mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION);
+ }
+ }
+ } else {
+ mPreviousScrollState = mNewState;
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * This is a specialized adapter for creating a list of weeks with
+ * selectable days. It can be configured to display the week number, start
+ * the week on a given day, show a reduced number of days, or display an
+ * arbitrary number of weeks at a time.
+ * </p>
+ *
+ * @hide
+ */
+ public class WeeksAdapter extends BaseAdapter implements OnTouchListener {
+
+ /**
+ * The default maximum year supported by the Date Time Picker.
+ */
+ public static final int DEFAULT_MAX_CALENDAR_YEAR = 2100;
+
+ /**
+ * The default minimum year supported by the Date Time Picker.
+ */
+ public static final int DEFAULT_MIN_CALENDAR_YEAR = 1900;
+
+ /**
+ * The number of weeks to display at a time.
+ */
+ public static final String WEEK_PARAMS_NUM_WEEKS = "num_weeks";
+
+ /**
+ * Which month should be in focus currently.
+ */
+ public static final String WEEK_PARAMS_FOCUS_MONTH = "focus_month";
+
+ /**
+ * Whether the week number should be shown. Non-zero to show them.
+ */
+ public static final String WEEK_PARAMS_SHOW_WEEK = "week_numbers";
+
+ /**
+ * Which day the week should start on. {@link Time#SUNDAY} through
+ * {@link Time#SATURDAY}.
+ */
+ public static final String WEEK_PARAMS_WEEK_START = "week_start";
+
+ /**
+ * The year of the highlighted day.
+ */
+ public static final String WEEK_PARAMS_YEAR = "selected_year";
+
+ /**
+ * The month of the highlighted day.
+ */
+ public static final String WEEK_PARAMS_MONTH = "selected_month";
+
+ /**
+ * The year of the highlighted day.
+ */
+ public static final String WEEK_PARAMS_DAY_OF_MONTH = "selected_day_of_month";
+
+ /**
+ * The start date of the supported interval.
+ */
+ public static final String WEEK_PARAMS_START_DATE_RANGE_MILLIS = "start_date_gange_millis";
+
+ /**
+ * The end date of the supported interval.
+ */
+ public static final String WEEK_PARAMS_END_DATE_RANGE_MILLIS = "end_date_gange_millis";
+
+ /**
+ * How many days of the week to display [1-7].
+ */
+ public static final String WEEK_PARAMS_DAYS_PER_WEEK = "days_per_week";
+
+ protected int WEEK_7_OVERHANG_HEIGHT = 7;
+
+ protected int mSelectedWeek;
+
+ protected GestureDetector mGestureDetector;
+
+ protected int mFocusMonth = 0;
+
+ private final Calendar mSelectedDay = Calendar.getInstance();
+
+ private int mTotalWeekCount = -1;
+
+ public WeeksAdapter(Context context) {
+ mContext = context;
+
+ if (sScale == 0) {
+ sScale = context.getResources().getDisplayMetrics().density;
+ if (sScale != 1) {
+ WEEK_7_OVERHANG_HEIGHT *= sScale;
+ }
+ }
+ init();
+ }
+
+ /**
+ * Set up the gesture detector and selected time
+ */
+ protected void init() {
+ mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener());
+ mSelectedWeek = getWeeksDelta(mSelectedDay);
+ mTotalWeekCount = getWeeksDelta(mEndRangeDate);
+ }
+
+ /**
+ * Updates the selected day and related parameters.
+ *
+ * @param selectedDay The time to highlight
+ */
+ public void setSelectedDay(Calendar selectedDay) {
+ if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDay.get(Calendar.DAY_OF_YEAR)
+ && selectedDay.get(Calendar.YEAR) == mSelectedDay.get(Calendar.YEAR)) {
+ return;
+ }
+ mSelectedDay.setTimeInMillis(selectedDay.getTimeInMillis());
+ mSelectedDay.setTimeZone(selectedDay.getTimeZone());
+ mSelectedWeek = getWeeksDelta(mSelectedDay);
+ mFocusMonth = mSelectedDay.get(Calendar.MONTH);
+ notifyDataSetChanged();
+ invalidate(); // Test
+ }
+
+ /**
+ * @return The selected day of month.
+ */
+ public Calendar getSelectedDay() {
+ return mSelectedDay;
+ }
+
+ /**
+ * updates any config options that may have changed and refreshes the
+ * view
+ */
+ public void refresh() {
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mTotalWeekCount;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ WeekView v;
+ HashMap<String, Object> drawingParams = null;
+ if (convertView != null) {
+ v = (WeekView) convertView;
+ // We store the drawing parameters in the view so it can be
+ // recycled
+ drawingParams = (HashMap<String, Object>) v.getTag();
+ } else {
+ v = getNewView();
+ // Set up the new view
+ android.widget.AbsListView.LayoutParams params =
+ new android.widget.AbsListView.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ v.setLayoutParams(params);
+ v.setClickable(true);
+ v.setOnTouchListener(this);
+
+ drawingParams = new HashMap<String, Object>();
+ }
+
+ // pass in all the view parameters
+ putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SHOW_WK_NUM,
+ mShowWeekNumber ? 1 : 0);
+ putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK_START, mFirstDayOfWeek);
+ putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_NUM_DAYS, mDaysPerWeek);
+ putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK, position);
+ putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_FOCUS_MONTH, mFocusMonth);
+ putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SELECTED_DAY,
+ (mSelectedWeek == position) ? mSelectedDay.get(Calendar.DAY_OF_WEEK) : -1);
+ v.setWeekParams(drawingParams);
+
+ return v;
+ }
+
+ /**
+ * Puts the given <code>value</code> for the drawing
+ * <code>parameter</code> in the <code>drawingParams</code>.
+ */
+ private void putDrawingParementer(HashMap<String, Object> drawingParams, String parameter,
+ int value) {
+ int[] valueArray = (int[]) drawingParams.get(parameter);
+ if (valueArray == null) {
+ valueArray = new int[1];
+ drawingParams.put(parameter, valueArray);
+ }
+ valueArray[0] = value;
+ }
+
+ /**
+ * Creates a new WeekView and returns it. Override this to customize the
+ * view creation.
+ *
+ * @return A new WeekView
+ */
+ protected WeekView getNewView() {
+ return new WeekView(mContext);
+ }
+
+ /**
+ * Changes which month is in focus and updates the view.
+ *
+ * @param month The month to show as in focus [0-11]
+ */
+ public void setFocusMonth(int month) {
+ if (mFocusMonth == month) {
+ return;
+ }
+ mFocusMonth = month;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (mGestureDetector.onTouchEvent(event)) {
+ WeekView weekView = (WeekView) v;
+ weekView.getDayFromLocation(event.getX(), mTempCalendar);
+ if (mTempCalendar.get(Calendar.YEAR) != 0) {
+ onDayTapped(mTempCalendar);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Maintains the same hour/min/sec but moves the day to the tapped day.
+ *
+ * @param day The day that was tapped
+ */
+ protected void onDayTapped(Calendar day) {
+ setSelectedDay(day);
+ }
+
+ /**
+ * This is here so we can identify single tap events and set the
+ * selected day correctly
+ */
+ protected class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ return true;
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * This is a dynamic view for drawing a single week. It can be configured to
+ * display the week number, start the week on a given day, or show a reduced
+ * number of days. It is intended for use as a single view within a
+ * ListView. See {@link WeeksAdapter} for usage.
+ * </p>
+ *
+ * @hide
+ */
+ public class WeekView extends View {
+
+ /*
+ * These params can be passed into the view to control how it appears.
+ * {@link #VIEW_PARAMS_WEEK} is the only required field, though the
+ * default values are unlikely to fit most layouts correctly.
+ */
+
+ /**
+ * This sets the height of this week in pixels
+ */
+ public static final String VIEW_PARAMS_HEIGHT = "height";
+
+ /**
+ * This specifies the position (or weeks since the epoch) of this week.
+ */
+ public static final String VIEW_PARAMS_WEEK = "week";
+
+ /**
+ * This sets one of the days in this view as selected
+ * {@link Time#SUNDAY} through {@link Time#SATURDAY}.
+ */
+ public static final String VIEW_PARAMS_SELECTED_DAY = "selected_day";
+
+ /**
+ * Which day the week should start on. {@link Time#SUNDAY} through
+ * {@link Time#SATURDAY}.
+ */
+ public static final String VIEW_PARAMS_WEEK_START = "week_start";
+
+ /**
+ * How many days to display at a time. Days will be displayed starting
+ * with {@link #mFirstDay}.
+ */
+ public static final String VIEW_PARAMS_NUM_DAYS = "num_days";
+
+ /**
+ * Which month is currently in focus, as defined by {@link Time#month}
+ * [0-11].
+ */
+ public static final String VIEW_PARAMS_FOCUS_MONTH = "focus_month";
+
+ /**
+ * If this month should display week numbers. false if 0, true
+ * otherwise.
+ */
+ public static final String VIEW_PARAMS_SHOW_WK_NUM = "show_wk_num";
+
+ protected int mDefaultHeight = 32;
+
+ protected int mMinHeight = 10;
+
+ protected static final int DEFAULT_SELECTED_DAY = -1;
+
+ protected static final int DEFAULT_WEEK_START = Calendar.SUNDAY;
+
+ protected static final int DEFAULT_NUM_DAYS = 7;
+
+ protected static final int DEFAULT_SHOW_WK_NUM = 0;
+
+ protected static final int DEFAULT_FOCUS_MONTH = -1;
+
+ protected static final int DAY_SEPARATOR_WIDTH = 1;
+
+ protected int mNumberTextSize = 14;
+
+ // affects the padding on the sides of this view
+ protected int mPadding = 0;
+
+ protected final Rect mTempRect = new Rect();
+
+ protected final Paint mDrawPaint = new Paint();
+
+ protected Paint mMonthNumDrawPaint = new Paint();
+
+ protected Drawable mSelectedDayLine;
+
+ protected final int mSelectionBackgroundColor;
+
+ protected final int mFocusedMonthDateColor;
+
+ protected final int mOtherMonthDateColor;
+
+ protected final int mGridLinesColor;
+
+ protected final int mWeekNumberColor;
+
+ // Cache the number strings so we don't have to recompute them each time
+ protected String[] mDayNumbers;
+
+ // Quick lookup for checking which days are in the focus month
+ protected boolean[] mFocusDay;
+
+ // The first day displayed by this item
+ protected Calendar mFirstDay;
+
+ // The month of the first day in this week
+ protected int mMonthOfFirstWeekDay = -1;
+
+ // The month of the last day in this week
+ protected int mLastWeekDayMonth = -1;
+
+ // The position of this week, equivalent to weeks since the week of Jan
+ // 1st, 1900
+ protected int mWeek = -1;
+
+ // Quick reference to the width of this view, matches parent
+ protected int mWidth;
+
+ // The height this view should draw at in pixels, set by height param
+ protected int mHeight = mDefaultHeight;
+
+ // Whether the week number should be shown
+ protected boolean mShowWeekNum = false;
+
+ // If this view contains the selected day
+ protected boolean mHasSelectedDay = false;
+
+ // Which day is selected [0-6] or -1 if no day is selected
+ protected int mSelectedDay = DEFAULT_SELECTED_DAY;
+
+ // How many days to display
+ protected int mNumDays = DEFAULT_NUM_DAYS;
+
+ // The number of days + a spot for week number if it is displayed
+ protected int mNumCells = mNumDays;
+
+ // The left edge of the selected day
+ protected int mSelectedLeft = -1;
+
+ // The right edge of the selected day
+ protected int mSelectedRight = -1;
+
+ public WeekView(Context context) {
+ super(context);
+
+ TypedValue outTypedValue = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.dayPickerWeekViewStyle, outTypedValue, true);
+ TypedArray attributesArray = context.obtainStyledAttributes(outTypedValue.resourceId,
+ R.styleable.DayPickerWeekView);
+
+ mSelectionBackgroundColor = attributesArray.getColor(
+ R.styleable.DayPickerWeekView_selectionBackgroundColor, 0);
+ mFocusedMonthDateColor = attributesArray.getColor(
+ R.styleable.DayPickerWeekView_focusedMonthDateColor, 0);
+ mOtherMonthDateColor = attributesArray.getColor(
+ R.styleable.DayPickerWeekView_otherMonthDateColor, 0);
+ mGridLinesColor = attributesArray.getColor(
+ R.styleable.DayPickerWeekView_gridLinesColor, 0);
+ mWeekNumberColor = attributesArray.getColor(
+ R.styleable.DayPickerWeekView_weekNumberColor, 0);
+ mSelectedDayLine = attributesArray
+ .getDrawable(R.styleable.DayPickerWeekView_selectedDayLine);
+ attributesArray.recycle();
+
+ if (sScale == 0) {
+ sScale = context.getResources().getDisplayMetrics().density;
+ if (sScale != 1) {
+ mDefaultHeight *= sScale;
+ mMinHeight *= sScale;
+ mNumberTextSize *= sScale;
+ }
+ }
+
+ // Sets up any standard paints that will be used
+ setPaintProperties();
+ }
+
+ /**
+ * Sets all the parameters for displaying this week. The only required
+ * parameter is the week number. Other parameters have a default value
+ * and will only update if a new value is included, except for focus
+ * month, which will always default to no focus month if no value is
+ * passed in. See {@link #VIEW_PARAMS_HEIGHT} for more info on
+ * parameters.
+ *
+ * @param params A map of the new parameters, see
+ * {@link #VIEW_PARAMS_HEIGHT}
+ */
+ public void setWeekParams(HashMap<String, Object> params) {
+ if (!params.containsKey(VIEW_PARAMS_WEEK)) {
+ throw new InvalidParameterException(
+ "You must specify the week number for this view");
+ }
+ setTag(params);
+ // We keep the current value for any params not present
+ if (params.containsKey(VIEW_PARAMS_HEIGHT)) {
+ mHeight = ((int[]) params.get(VIEW_PARAMS_HEIGHT))[0];
+ if (mHeight < mMinHeight) {
+ mHeight = mMinHeight;
+ }
+ }
+ if (params.containsKey(VIEW_PARAMS_SELECTED_DAY)) {
+ mSelectedDay = ((int[]) params.get(VIEW_PARAMS_SELECTED_DAY))[0];
+ }
+ mHasSelectedDay = mSelectedDay != -1;
+ if (params.containsKey(VIEW_PARAMS_NUM_DAYS)) {
+ mNumDays = ((int[]) params.get(VIEW_PARAMS_NUM_DAYS))[0];
+ }
+ if (params.containsKey(VIEW_PARAMS_SHOW_WK_NUM)) {
+ if (((int[]) params.get(VIEW_PARAMS_SHOW_WK_NUM))[0] != 0) {
+ mNumCells = mNumDays + 1;
+ mShowWeekNum = true;
+ } else {
+ mShowWeekNum = false;
+ }
+ } else {
+ mNumCells = mShowWeekNum ? mNumDays + 1 : mNumDays;
+ }
+ mWeek = ((int[]) params.get(VIEW_PARAMS_WEEK))[0];
+ mTempCalendar.clear();
+ mTempCalendar.set(1900, 0, 1);
+ mTempCalendar.add(Calendar.WEEK_OF_YEAR, mWeek);
+ if (params.containsKey(VIEW_PARAMS_WEEK_START)) {
+ mTempCalendar.setFirstDayOfWeek(((int[]) params.get(VIEW_PARAMS_WEEK_START))[0]);
+ } else {
+ mTempCalendar.setFirstDayOfWeek(DEFAULT_WEEK_START);
+ }
+
+ // Allocate space for caching the day numbers and focus values
+ mDayNumbers = new String[mNumCells];
+ mFocusDay = new boolean[mNumCells];
+
+ // If we're showing the week number calculate it based on Monday
+ int i = 0;
+ if (mShowWeekNum) {
+ mDayNumbers[0] = Integer.toString(mTempCalendar.get(Calendar.WEEK_OF_YEAR));
+ i++;
+ }
+
+ // Now adjust our starting day based on the start day of the week
+ int diff = mTempCalendar.getFirstDayOfWeek() - mTempCalendar.get(Calendar.DAY_OF_WEEK);
+ mTempCalendar.add(Calendar.DAY_OF_MONTH, diff);
+
+ mFirstDay = (Calendar) mTempCalendar.clone();
+
+ mMonthOfFirstWeekDay = mTempCalendar.get(Calendar.MONTH);
+
+ int focusMonth = params.containsKey(VIEW_PARAMS_FOCUS_MONTH) ? ((int[]) params
+ .get(VIEW_PARAMS_FOCUS_MONTH))[0] : DEFAULT_FOCUS_MONTH;
+
+ for (; i < mNumCells; i++) {
+ mFocusDay[i] = (mTempCalendar.get(Calendar.MONTH) == focusMonth);
+ mDayNumbers[i] = Integer.toString(mTempCalendar.get(Calendar.DAY_OF_MONTH));
+ mTempCalendar.add(Calendar.DAY_OF_MONTH, 1);
+ }
+ // We do one extra add at the end of the loop, if that pushed us to
+ // new month undo it
+ if (mTempCalendar.get(Calendar.DAY_OF_MONTH) == 1) {
+ mTempCalendar.add(Calendar.DAY_OF_MONTH, -1);
+ }
+ mLastWeekDayMonth = mTempCalendar.get(Calendar.MONTH);
+
+ updateSelectionPositions();
+ }
+
+ /**
+ * Sets up the text and style properties for painting. Override this if
+ * you want to use a different paint.
+ */
+ protected void setPaintProperties() {
+ mDrawPaint.setFakeBoldText(false);
+ mDrawPaint.setAntiAlias(true);
+ mDrawPaint.setTextSize(mNumberTextSize);
+ mDrawPaint.setStyle(Style.FILL);
+
+ mMonthNumDrawPaint.setFakeBoldText(true);
+ mMonthNumDrawPaint.setAntiAlias(true);
+ mMonthNumDrawPaint.setTextSize(mNumberTextSize);
+ mMonthNumDrawPaint.setColor(mFocusedMonthDateColor);
+ mMonthNumDrawPaint.setStyle(Style.FILL);
+ mMonthNumDrawPaint.setTextAlign(Align.CENTER);
+ }
+
+ /**
+ * Returns the month of the first day in this week.
+ *
+ * @return The month the first day of this view is in.
+ */
+ public int getMonthOfFirstWeekDay() {
+ return mMonthOfFirstWeekDay;
+ }
+
+ /**
+ * Returns the month of the last day in this week
+ *
+ * @return The month the last day of this view is in
+ */
+ public int getMonthOfLastWeekDay() {
+ return mLastWeekDayMonth;
+ }
+
+ /**
+ * Returns the first day in this view.
+ *
+ * @return The first day in the view.
+ */
+ public Calendar getFirstDay() {
+ return mFirstDay;
+ }
+
+ /**
+ * Returns the number of days this view will display.
+ */
+ public int getNumDays() {
+ return mNumDays;
+ }
+
+ /**
+ * Calculates the day that the given x position is in, accounting for
+ * week number. Returns a Time referencing that day or null if
+ *
+ * @param x The x position of the touch eventy
+ */
+ public void getDayFromLocation(float x, Calendar outCalendar) {
+ int dayStart = mShowWeekNum ? (mWidth - mPadding * 2) / mNumCells + mPadding : mPadding;
+ if (x < dayStart || x > mWidth - mPadding) {
+ outCalendar.set(0, 0, 0, 0, 0, 0);
+ return;
+ }
+ // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
+ int dayPosition = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));
+ outCalendar.setTimeZone(mFirstDay.getTimeZone());
+ outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
+ outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ drawBackground(canvas);
+ drawWeekNums(canvas);
+ drawDaySeparators(canvas);
+ }
+
+ /**
+ * This draws the selection highlight if a day is selected in this week.
+ * Override this method if you wish to have a different background
+ * drawn.
+ *
+ * @param canvas The canvas to draw on
+ */
+ protected void drawBackground(Canvas canvas) {
+ if (!mHasSelectedDay) {
+ return;
+ }
+ mDrawPaint.setColor(mSelectionBackgroundColor);
+
+ mTempRect.top = DAY_SEPARATOR_WIDTH;
+ mTempRect.bottom = mHeight;
+ mTempRect.left = mShowWeekNum ? mPadding + (mWidth - mPadding * 2) / mNumCells
+ : mPadding;
+ mTempRect.right = mSelectedLeft - 2;
+ canvas.drawRect(mTempRect, mDrawPaint);
+
+ mTempRect.left = mSelectedRight + 3;
+ mTempRect.right = mWidth - mPadding;
+ canvas.drawRect(mTempRect, mDrawPaint);
+ }
+
+ /**
+ * Draws the week and month day numbers for this week. Override this
+ * method if you need different placement.
+ *
+ * @param canvas The canvas to draw on
+ */
+ protected void drawWeekNums(Canvas canvas) {
+ float textHeight = mDrawPaint.getTextSize();
+ int y = (int) ((mHeight + textHeight) / 2) - DAY_SEPARATOR_WIDTH;
+ int nDays = mNumCells;
+
+ mDrawPaint.setTextAlign(Align.CENTER);
+ int i = 0;
+ int divisor = 2 * nDays;
+ if (mShowWeekNum) {
+ mDrawPaint.setColor(mWeekNumberColor);
+ int x = (mWidth - mPadding * 2) / divisor + mPadding;
+ canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+ i++;
+ }
+ for (; i < nDays; i++) {
+ mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+ : mOtherMonthDateColor);
+ int x = (2 * i + 1) * (mWidth - mPadding * 2) / divisor + mPadding;
+ canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+ }
+ }
+
+ /**
+ * Draws a horizontal line for separating the weeks. Override this
+ * method if you want custom separators.
+ *
+ * @param canvas The canvas to draw on
+ */
+ protected void drawDaySeparators(Canvas canvas) {
+ mDrawPaint.setColor(mGridLinesColor);
+ mDrawPaint.setStrokeWidth(DAY_SEPARATOR_WIDTH);
+ float x = mShowWeekNum ? mPadding + (mWidth - mPadding * 2) / mNumCells : mPadding;
+ canvas.drawLine(x, 0, mWidth - mPadding, 0, mDrawPaint);
+
+ if (mHasSelectedDay) {
+ mSelectedDayLine.setBounds(mSelectedLeft - 2, DAY_SEPARATOR_WIDTH,
+ mSelectedLeft + 4, mHeight + 1);
+ mSelectedDayLine.draw(canvas);
+ mSelectedDayLine.setBounds(mSelectedRight - 3, DAY_SEPARATOR_WIDTH,
+ mSelectedRight + 3, mHeight + 1);
+ mSelectedDayLine.draw(canvas);
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mWidth = w;
+ updateSelectionPositions();
+ }
+
+ /**
+ * This calculates the positions for the selected day lines.
+ */
+ protected void updateSelectionPositions() {
+ if (mHasSelectedDay) {
+ int selectedPosition = mSelectedDay - mTempCalendar.getFirstDayOfWeek();
+ if (selectedPosition < 0) {
+ selectedPosition += 7;
+ }
+ if (mShowWeekNum) {
+ selectedPosition++;
+ }
+ mSelectedLeft = selectedPosition * (mWidth - mPadding * 2) / mNumCells + mPadding;
+ mSelectedRight = (selectedPosition + 1) * (mWidth - mPadding * 2) / mNumCells
+ + mPadding;
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
+ }
+ }
+}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 940fec1..26e191d 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -76,6 +76,8 @@
boolean mForegroundBoundsChanged = false;
+ private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.LEFT;
+
public FrameLayout(Context context) {
super(context);
}
@@ -307,41 +309,42 @@
int childLeft = parentLeft;
int childTop = parentTop;
- final int gravity = lp.gravity;
+ int gravity = lp.gravity;
+ if (gravity == -1) {
+ gravity = DEFAULT_CHILD_GRAVITY;
+ }
- if (gravity != -1) {
- final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+ final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
- switch (horizontalGravity) {
- case Gravity.LEFT:
- childLeft = parentLeft + lp.leftMargin;
- break;
- case Gravity.CENTER_HORIZONTAL:
- childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
- lp.leftMargin - lp.rightMargin;
- break;
- case Gravity.RIGHT:
- childLeft = parentRight - width - lp.rightMargin;
- break;
- default:
- childLeft = parentLeft + lp.leftMargin;
- }
+ switch (horizontalGravity) {
+ case Gravity.LEFT:
+ childLeft = parentLeft + lp.leftMargin;
+ break;
+ case Gravity.CENTER_HORIZONTAL:
+ childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
+ lp.leftMargin - lp.rightMargin;
+ break;
+ case Gravity.RIGHT:
+ childLeft = parentRight - width - lp.rightMargin;
+ break;
+ default:
+ childLeft = parentLeft + lp.leftMargin;
+ }
- switch (verticalGravity) {
- case Gravity.TOP:
- childTop = parentTop + lp.topMargin;
- break;
- case Gravity.CENTER_VERTICAL:
- childTop = parentTop + (parentBottom - parentTop - height) / 2 +
- lp.topMargin - lp.bottomMargin;
- break;
- case Gravity.BOTTOM:
- childTop = parentBottom - height - lp.bottomMargin;
- break;
- default:
- childTop = parentTop + lp.topMargin;
- }
+ switch (verticalGravity) {
+ case Gravity.TOP:
+ childTop = parentTop + lp.topMargin;
+ break;
+ case Gravity.CENTER_VERTICAL:
+ childTop = parentTop + (parentBottom - parentTop - height) / 2 +
+ lp.topMargin - lp.bottomMargin;
+ break;
+ case Gravity.BOTTOM:
+ childTop = parentBottom - height - lp.bottomMargin;
+ break;
+ default:
+ childTop = parentTop + lp.topMargin;
}
child.layout(childLeft, childTop, childLeft + width, childTop + height);
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index c05e3ad..50867b9 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1420,8 +1420,8 @@
final int height = getHeight();
canvas.rotate(270);
- canvas.translate(-height * 1.5f, Math.min(0, scrollX));
- mEdgeGlowLeft.setSize(getHeight() * 2, getWidth());
+ canvas.translate(-height, Math.min(0, scrollX));
+ mEdgeGlowLeft.setSize(getHeight(), getWidth());
if (mEdgeGlowLeft.draw(canvas)) {
invalidate();
}
@@ -1433,8 +1433,9 @@
final int height = getHeight();
canvas.rotate(90);
- canvas.translate(-height / 2, -(Math.max(getScrollRange(), scrollX) + width));
- mEdgeGlowRight.setSize(height * 2, width);
+ canvas.translate(0,
+ -(Math.max(getScrollRange(), scrollX) + width));
+ mEdgeGlowRight.setSize(height, width);
if (mEdgeGlowRight.draw(canvas)) {
invalidate();
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 43d194f..bdd2e2c 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -30,8 +30,8 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.Rect;
import android.graphics.Paint.Align;
+import android.graphics.Rect;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;
@@ -41,11 +41,11 @@
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.LayoutInflater.Filter;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
-import android.view.LayoutInflater.Filter;
import android.view.animation.OvershootInterpolator;
import android.view.inputmethod.InputMethodManager;
@@ -166,7 +166,12 @@
/**
* Listener to be notified upon current value change.
*/
- private OnChangedListener mListener;
+ private OnChangedListener mOnChangedListener;
+
+ /**
+ * Listener to be notified upon scroll state change.
+ */
+ private OnScrollListener mOnScrollListener;
/**
* Formatter for for displaying the current value.
@@ -308,6 +313,11 @@
private final Rect mTempRect = new Rect();
/**
+ * The current scroll state of the number picker.
+ */
+ private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+ /**
* The callback interface used to indicate the number value has changed.
*/
public interface OnChangedListener {
@@ -320,6 +330,36 @@
}
/**
+ * Interface for listening to the picker scroll state.
+ */
+ public interface OnScrollListener {
+
+ /**
+ * The view is not scrolling.
+ */
+ public static int SCROLL_STATE_IDLE = 0;
+
+ /**
+ * The user is scrolling using touch, and their finger is still on the screen.
+ */
+ public static int SCROLL_STATE_TOUCH_SCROLL = 1;
+
+ /**
+ * The user had previously been scrolling using touch and performed a fling.
+ */
+ public static int SCROLL_STATE_FLING = 2;
+
+ /**
+ * Callback method to be invoked while the number picker is being scrolled.
+ *
+ * @param view The view whose scroll state is being reported
+ * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
+ * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
+ */
+ public void onScrollStateChanged(NumberPicker view, int scrollState);
+ }
+
+ /**
* Interface used to format the number into a string for presentation
*/
public interface Formatter {
@@ -492,11 +532,15 @@
mBeginEditOnUpEvent = false;
mAdjustScrollerOnUpEvent = true;
if (mDrawSelectorWheel) {
- mBeginEditOnUpEvent = mFlingScroller.isFinished()
+ boolean scrollersFinished = mFlingScroller.isFinished()
&& mAdjustScroller.isFinished();
+ if (!scrollersFinished) {
+ mFlingScroller.forceFinished(true);
+ mAdjustScroller.forceFinished(true);
+ tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE);
+ }
+ mBeginEditOnUpEvent = scrollersFinished;
mAdjustScrollerOnUpEvent = true;
- mFlingScroller.forceFinished(true);
- mAdjustScroller.forceFinished(true);
hideInputControls();
return true;
}
@@ -512,6 +556,7 @@
int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
if (deltaDownY > mTouchSlop) {
mBeginEditOnUpEvent = false;
+ tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
setDrawSelectorWheel(true);
hideInputControls();
return true;
@@ -531,10 +576,12 @@
switch (action) {
case MotionEvent.ACTION_MOVE:
float currentMoveY = ev.getY();
- if (mBeginEditOnUpEvent) {
+ if (mBeginEditOnUpEvent
+ || mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
if (deltaDownY > mTouchSlop) {
mBeginEditOnUpEvent = false;
+ tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
}
int deltaMoveY = (int) (currentMoveY - mLastMotionEventY);
@@ -550,6 +597,7 @@
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mInputText, 0);
+ mInputText.setSelection(0, mInputText.getText().length());
return true;
}
VelocityTracker velocityTracker = mVelocityTracker;
@@ -557,6 +605,7 @@
int initialVelocity = (int) velocityTracker.getYVelocity();
if (Math.abs(initialVelocity) > mMinimumFlingVelocity) {
fling(initialVelocity);
+ tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_FLING);
} else {
if (mAdjustScrollerOnUpEvent) {
if (mFlingScroller.isFinished() && mAdjustScroller.isFinished()) {
@@ -689,10 +738,19 @@
/**
* Set the callback that indicates the number has been adjusted by the user.
*
- * @param listener the callback, should not be null.
+ * @param onChangeListener the callback, should not be null.
*/
- public void setOnChangeListener(OnChangedListener listener) {
- mListener = listener;
+ public void setOnChangeListener(OnChangedListener onChangeListener) {
+ mOnChangedListener = onChangeListener;
+ }
+
+ /**
+ * Set the callback that in notified for scroll state changes.
+ *
+ * @param onScrollListener the callback, should not be null.
+ */
+ public void setOnScrollListener(OnScrollListener onScrollListener) {
+ mOnScrollListener = onScrollListener;
}
/**
@@ -966,6 +1024,7 @@
private void onScrollerFinished(Scroller scroller) {
if (scroller == mFlingScroller) {
postAdjustScrollerCommand(0);
+ tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE);
} else {
showInputControls();
updateInputTextView();
@@ -973,6 +1032,17 @@
}
/**
+ * Notifies the scroll listener for the given <code>scrollState</code>
+ * if the scroll state differs from the current scroll state.
+ */
+ private void tryNotifyScrollListener(int scrollState) {
+ if (mOnScrollListener != null && mScrollState != scrollState) {
+ mScrollState = scrollState;
+ mOnScrollListener.onScrollStateChanged(this, scrollState);
+ }
+ }
+
+ /**
* Flings the selector with the given <code>velocityY</code>.
*/
private void fling(int velocityY) {
@@ -1118,7 +1188,8 @@
scrollSelectorValue = "";
} else {
if (mDisplayedValues != null) {
- scrollSelectorValue = mDisplayedValues[selectorIndex];
+ int displayedValueIndex = selectorIndex - mStart;
+ scrollSelectorValue = mDisplayedValues[displayedValueIndex];
} else {
scrollSelectorValue = formatNumber(selectorIndex);
}
@@ -1167,8 +1238,8 @@
* NumberPicker.
*/
private void notifyChange(int previous, int current) {
- if (mListener != null) {
- mListener.onChanged(this, previous, mCurrent);
+ if (mOnChangedListener != null) {
+ mOnChangedListener.onChanged(this, previous, mCurrent);
}
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 9fa90dc..f25edd8 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1467,8 +1467,8 @@
final int restoreCount = canvas.save();
final int width = getWidth();
- canvas.translate(-width / 2, Math.min(0, scrollY));
- mEdgeGlowTop.setSize(width * 2, getHeight());
+ canvas.translate(0, Math.min(0, scrollY));
+ mEdgeGlowTop.setSize(width, getHeight());
if (mEdgeGlowTop.draw(canvas)) {
invalidate();
}
@@ -1479,9 +1479,9 @@
final int width = getWidth();
final int height = getHeight();
- canvas.translate(-width / 2, Math.max(getScrollRange(), scrollY) + height);
+ canvas.translate(-width, Math.max(getScrollRange(), scrollY) + height);
canvas.rotate(180, width, 0);
- mEdgeGlowBottom.setSize(width * 2, height);
+ mEdgeGlowBottom.setSize(width, height);
if (mEdgeGlowBottom.draw(canvas)) {
invalidate();
}
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index b32bd42..e499e54 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1271,7 +1271,7 @@
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
- if (hasWindowFocus) {
+ if (hasWindowFocus && mSearchView.hasFocus() && getVisibility() == VISIBLE) {
InputMethodManager inputManager = (InputMethodManager) getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(this, 0);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a86610dd..144cf9c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3933,6 +3933,9 @@
hideError();
}
+ if (mBlink != null) {
+ mBlink.cancel();
+ }
hideControllers();
}
@@ -6282,11 +6285,7 @@
mCursorVisible = visible;
invalidate();
- if (visible) {
- makeBlink();
- } else if (mBlink != null) {
- mBlink.removeCallbacks(mBlink);
- }
+ makeBlink();
// InsertionPointCursorController depends on mCursorVisible
prepareCursorControllers();
@@ -6782,7 +6781,7 @@
}
private void makeBlink() {
- if (!mCursorVisible) {
+ if (!mCursorVisible || !isTextEditable()) {
if (mBlink != null) {
mBlink.removeCallbacks(mBlink);
}
@@ -7134,6 +7133,7 @@
mLayout != null;
if (!mInsertionControllerEnabled) {
+ hideInsertionPointCursorController();
mInsertionPointCursorController = null;
}
@@ -7388,14 +7388,14 @@
}
private boolean canSelectText() {
- return textCanBeSelected() && mText.length() != 0;
+ return hasSelectionController() && mText.length() != 0;
}
private boolean textCanBeSelected() {
// prepareCursorController() relies on this method.
// If you change this condition, make sure prepareCursorController is called anywhere
// the value of this condition might be changed.
- return (mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily());
+ return mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily();
}
private boolean canCut() {
@@ -7529,6 +7529,10 @@
}
private void selectCurrentWord() {
+ if (!canSelectText()) {
+ return;
+ }
+
if (hasPasswordTransformationMethod()) {
// selectCurrentWord is not available on a password field and would return an
// arbitrary 10-charater selection around pressed position. Select all instead.
@@ -7544,7 +7548,6 @@
minOffset = getSelectionStart();
maxOffset = getSelectionEnd();
} else {
- // selectionModifierCursorController is guaranteed to exist at that point
SelectionModifierCursorController selectionController = getSelectionController();
minOffset = selectionController.getMinTouchOffset();
maxOffset = selectionController.getMaxTouchOffset();
@@ -7921,12 +7924,8 @@
selectCurrentWord();
ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
- if (actionModeCallback != null) {
- mSelectionActionMode = startActionMode(actionModeCallback);
- return mSelectionActionMode != null;
- }
-
- return false;
+ mSelectionActionMode = startActionMode(actionModeCallback);
+ return mSelectionActionMode != null;
}
/**
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 6cf1387..e66eb8d 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -184,7 +184,7 @@
setEnabled(false);
}
}
-
+
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index 36f45b2..6039cc2 100755
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -26,6 +26,8 @@
import android.widget.Toast;
import android.util.Log;
import android.location.LocationManager;
+
+import com.android.internal.R;
import com.android.internal.location.GpsNetInitiatedHandler;
/**
@@ -42,10 +44,6 @@
private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE;
private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON_NEGATIVE;
- // Dialog button text
- public static final String BUTTON_TEXT_ACCEPT = "Accept";
- public static final String BUTTON_TEXT_DENY = "Deny";
-
// Received ID from intent, -1 when no notification is in progress
private int notificationId = -1;
@@ -67,12 +65,13 @@
// Set up the "dialog"
final Intent intent = getIntent();
final AlertController.AlertParams p = mAlertParams;
+ Context context = getApplicationContext();
p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
p.mTitle = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TITLE);
p.mMessage = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_MESSAGE);
- p.mPositiveButtonText = BUTTON_TEXT_ACCEPT;
+ p.mPositiveButtonText = String.format(context.getString(R.string.gpsVerifYes));
p.mPositiveButtonListener = this;
- p.mNegativeButtonText = BUTTON_TEXT_DENY;
+ p.mNegativeButtonText = String.format(context.getString(R.string.gpsVerifNo));
p.mNegativeButtonListener = this;
notificationId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1);
diff --git a/core/java/com/android/internal/widget/DrawableHolder.java b/core/java/com/android/internal/widget/DrawableHolder.java
index a528aeb..947e0f3 100644
--- a/core/java/com/android/internal/widget/DrawableHolder.java
+++ b/core/java/com/android/internal/widget/DrawableHolder.java
@@ -87,15 +87,12 @@
* @param property
*/
public void removeAnimationFor(String property) {
- ArrayList<ObjectAnimator> removalList = new ArrayList<ObjectAnimator>();
- for (ObjectAnimator currentAnim : mAnimators) {
+ ArrayList<ObjectAnimator> removalList = (ArrayList<ObjectAnimator>)mAnimators.clone();
+ for (ObjectAnimator currentAnim : removalList) {
if (property.equals(currentAnim.getPropertyName())) {
currentAnim.cancel();
- removalList.add(currentAnim);
}
}
- if (DBG) Log.v(TAG, "Remove list size: " + removalList.size());
- mAnimators.removeAll(removalList);
}
/**
diff --git a/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
new file mode 100644
index 0000000..ed1a5e9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
new file mode 100644
index 0000000..f264cb6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_chat.png b/core/res/res/drawable-mdpi/stat_notify_chat.png
index 068b7ec..8cf02cc 100644
--- a/core/res/res/drawable-mdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-mdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 4fd46b3..5c023ee 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -19,45 +19,74 @@
<!-- Layout of date picker-->
-<!-- Warning: everything within the parent is removed and re-ordered depending
- on the date format selected by the user. -->
+<!-- Warning: everything within the "pickers" layout is removed and re-ordered
+ depending on the date format selected by the user.
+-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/parent"
- android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
android:layout_gravity="center_horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
+ android:orientation="horizontal"
+ android:gravity="center">
- <!-- Month -->
- <NumberPicker
- android:id="@+id/month"
- android:layout_width="80dip"
+ <LinearLayout android:id="@+id/pickers"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="1dip"
- android:layout_marginRight="1dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
+ android:layout_marginRight="15dip"
+ android:layout_weight="0.5"
+ android:orientation="horizontal"
+ android:gravity="center">
- <!-- Day -->
- <NumberPicker
- android:id="@+id/day"
- android:layout_width="80dip"
- android:layout_height="wrap_content"
- android:layout_marginLeft="1dip"
- android:layout_marginRight="1dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
+ <!-- Month -->
+ <NumberPicker
+ android:id="@+id/month"
+ android:layout_width="48dip"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dip"
+ android:layout_marginRight="15dip"
+ android:layout_marginTop="35dip"
+ android:layout_marginBottom="35dip"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
- <!-- Year -->
- <NumberPicker
- android:id="@+id/year"
- android:layout_width="95dip"
- android:layout_height="wrap_content"
- android:layout_marginLeft="1dip"
- android:layout_marginRight="1dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
+ <!-- Day -->
+ <NumberPicker
+ android:id="@+id/day"
+ android:layout_width="48dip"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dip"
+ android:layout_marginRight="15dip"
+ android:layout_marginTop="35dip"
+ android:layout_marginBottom="35dip"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
+
+ <!-- Year -->
+ <NumberPicker
+ android:id="@+id/year"
+ android:layout_width="48dip"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dip"
+ android:layout_marginRight="15dip"
+ android:layout_marginTop="35dip"
+ android:layout_marginBottom="35dip"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
+
+ </LinearLayout>
+
+ <!-- mini-month day-picker -->
+ <DayPicker
+ android:id="@+id/mini_month_day_picker"
+ android:layout_width="200dip"
+ android:layout_height="230dip"
+ android:layout_marginLeft="15dip"
+ android:layout_weight="0.5"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
+
</LinearLayout>
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 949c8a3..90de1f5 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -17,9 +17,14 @@
*/
-->
+<!-- Note: We want the DatePicker to take as much space as possible, therefore
+ we set the width and height bigger than the max AlertDialog size
+ determined by our parent WeightedLinearLayout.
+
+ See: alert_dialog.xml
+-->
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/datePicker"
- android:padding="5dip"
android:layout_gravity="center_horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_width="250dip"
+ android:layout_height="600dip"/>
diff --git a/core/res/res/layout/day_picker.xml b/core/res/res/layout/day_picker.xml
new file mode 100644
index 0000000..46ab450
--- /dev/null
+++ b/core/res/res/layout/day_picker.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true" >
+
+ <TextView android:id="@+android:id/month_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:paddingTop="10dip"
+ android:paddingBottom="10dip"
+ style="@android:style/TextAppearance.Medium" />
+
+ <LinearLayout android:id="@+android:id/day_names"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="6dip"
+ android:layout_marginRight="2dip"
+ android:layout_marginLeft="2dip"
+ android:gravity="center">
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:visibility="gone" />
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ style="?android:attr/dayPickerWeekDayViewStyle" />
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ style="?android:attr/dayPickerWeekDayViewStyle" />
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ style="?android:attr/dayPickerWeekDayViewStyle" />
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ style="?android:attr/dayPickerWeekDayViewStyle" />
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ style="?android:attr/dayPickerWeekDayViewStyle" />
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ style="?android:attr/dayPickerWeekDayViewStyle" />
+
+ <TextView android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ style="?android:attr/dayPickerWeekDayViewStyle" />
+
+ </LinearLayout>
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:drawSelectorOnTop="false"
+ android:cacheColorHint="@android:color/transparent"
+ android:fastScrollEnabled="false"
+ android:overScrollMode="never" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index fa288422..bf81c18 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -30,7 +30,7 @@
android:id="@+id/hour"
android:layout_width="48dip"
android:layout_height="wrap_content"
- android:layout_marginRight="20dip"
+ android:layout_marginRight="13dip"
android:layout_marginTop="35dip"
android:layout_marginBottom="35dip"
android:focusable="true"
@@ -50,8 +50,8 @@
android:id="@+id/minute"
android:layout_width="48dip"
android:layout_height="wrap_content"
- android:layout_marginLeft="20dip"
- android:layout_marginRight="22dip"
+ android:layout_marginLeft="13dip"
+ android:layout_marginRight="15dip"
android:layout_marginTop="35dip"
android:layout_marginBottom="35dip"
android:focusable="true"
@@ -63,7 +63,7 @@
android:id="@+id/amPm"
android:layout_width="48dip"
android:layout_height="wrap_content"
- android:layout_marginLeft="22dip"
+ android:layout_marginLeft="15dip"
android:layout_marginTop="35dip"
android:layout_marginBottom="35dip"
android:focusable="true"
diff --git a/core/res/res/layout/time_picker_dialog.xml b/core/res/res/layout/time_picker_dialog.xml
index d5a6b5e..09326c8 100644
--- a/core/res/res/layout/time_picker_dialog.xml
+++ b/core/res/res/layout/time_picker_dialog.xml
@@ -22,4 +22,4 @@
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:padding="5dip" />
+ />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 109fb0d..81191ff 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -503,16 +503,23 @@
<attr name="listPopupWindowStyle" format="reference" />
<!-- Default PopupMenu style. -->
<attr name="popupMenuStyle" format="reference" />
- <!-- NumberPicker up button style -->
+
+ <!-- @hide NumberPicker up button style -->
<attr name="numberPickerUpButtonStyle" format="reference" />
- <!-- NumberPicker down button style -->
+ <!-- @hide NumberPicker down button style -->
<attr name="numberPickerDownButtonStyle" format="reference" />
- <!-- NumberPicker input text style -->
+ <!-- @hide NumberPicker input text style -->
<attr name="numberPickerInputTextStyle" format="reference" />
- <!-- NumberPicker the fading edge length of the selector wheel -->
+ <!-- @hide NumberPicker the fading edge length of the selector wheel -->
<attr name="numberPickerStyle" format="reference" />
+ <!-- @hide DayPicker$WeekView style-->
+ <attr name="dayPickerWeekViewStyle" format="reference" />
+
+ <!-- @hide DayPickerDayView style-->
+ <attr name="dayPickerWeekDayViewStyle" format="reference" />
+
<!-- =================== -->
<!-- Action bar styles -->
<!-- =================== -->
@@ -2943,6 +2950,16 @@
</declare-styleable>
<!-- @hide -->
+ <declare-styleable name="DayPickerWeekView">
+ <attr name="selectionBackgroundColor" format="color|reference" />
+ <attr name="focusedMonthDateColor" format="color|reference" />
+ <attr name="otherMonthDateColor" format="color|reference" />
+ <attr name="weekNumberColor" format="color|reference" />
+ <attr name="gridLinesColor" format="color|reference" />
+ <attr name="selectedDayLine" format="reference" />
+ </declare-styleable>
+
+ <!-- @hide -->
<declare-styleable name="NumberPicker">
<attr name="orientation" />
<attr name="solidColor" format="color|reference" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ae029e5..8fa1d32 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1567,6 +1567,6 @@
<public type="style" name="Holo.Light.ButtonBar.AlertDialog" />
<public type="style" name="Holo.SegmentedButton" />
<public type="style" name="Holo.Light.SegmentedButton" />
-
<public type="string" name="selectTextMode" />
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0f5ff05..2e235f0 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2295,6 +2295,8 @@
<!-- The title of the time picker dialog. [CHAR LIMIT=NONE] -->
<string name="time_picker_dialog_title">Set time</string>
+ <!-- The title of the date picker dialog. [CHAR LIMIT=NONE] -->
+ <string name="date_picker_dialog_title">Set date</string>
<!-- Name of the button in the date/time picker to accept the date/time change -->
<string name="date_time_set">Set</string>
@@ -2621,4 +2623,19 @@
<!-- ActionBar action to use the current selection to open the Find on page functionality [CHAR LIMIT=10]-->
<string name="find">Find</string>
+ <!-- Network positioning notification ticker. The name of the user (e.g. John Doe) who sent
+ the request is shown as a dynamic string. -->
+ <string name="gpsNotifTicker">Location request from <xliff:g id="name">%s</xliff:g></string>
+ <!-- Network positioning notification and verification title to inform the user about
+ an incoming location request. -->
+ <string name="gpsNotifTitle">Location request</string>
+ <!-- Network positioning notification message. The name of the user (e.g. John Doe) and
+ service (SUPL-service) who sent the request is shown as dynamic strings.
+ Translation should not be longer than master text. -->
+ <string name="gpsNotifMessage">Requested by <xliff:g id="name">%1$s</xliff:g> (<xliff:g id="service" example="SUPL-service">%2$s</xliff:g>)</string>
+ <!-- Network positioning verification Yes. Button to push to share location information. -->
+ <string name="gpsVerifYes">Yes</string>
+ <!-- Network positioning verification No. Button to push to deny sharing of location
+ information. -->
+ <string name="gpsVerifNo">No</string>
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 58553e1..8d7556f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -238,6 +238,11 @@
<item name="android:textColor">#ff272727</item>
</style>
+ <!-- @hide -->
+ <style name="TextAppearance.Small.DayPickerWeekDayView">
+ <item name="android:textStyle">bold</item>
+ </style>
+
<!-- Widget Styles -->
<style name="Widget">
@@ -468,21 +473,35 @@
<item name="android:background">@android:drawable/btn_default</item>
</style>
+ <!-- @hide -->
+ <style name="Widget.DayPickerWeekView">
+ <item name="android:selectionBackgroundColor">#330099FF</item>
+ <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
+ <item name="android:otherMonthDateColor">#66FFFFFF</item>
+ <item name="android:weekNumberColor">#33FFFFFF</item>
+ <item name="android:gridLinesColor">#19FFFFFF</item>
+ <item name="selectedDayLine">@android:drawable/simple_week_dayline_holo_light</item>
+ </style>
+
+ <!-- @hide -->
<style name="Widget.NumberPicker">
<item name="android:orientation">vertical</item>
<item name="android:fadingEdge">vertical</item>
<item name="android:fadingEdgeLength">50dip</item>
- <item name="android:solidColor">?android:attr/colorBackground</item>
+ <item name="android:solidColor">@android:color/transparent</item>
</style>
+ <!-- @hide -->
<style name="Widget.ImageButton.NumberPickerUpButton">
<item name="android:background">@android:drawable/timepicker_up_btn</item>
</style>
+ <!-- @hide -->
<style name="Widget.ImageButton.NumberPickerDownButton">
<item name="android:background">@android:drawable/timepicker_down_btn</item>
</style>
+ <!-- @hide -->
<style name="Widget.EditText.NumberPickerInputText">
<item name="android:textAppearance">@style/TextAppearance.Large.Inverse.NumberPickerInputText</item>
<item name="android:gravity">center</item>
@@ -834,6 +853,7 @@
<item name="android:textStyle">bold</item>
</style>
+ <!-- @hide -->
<style name="TextAppearance.Large.Inverse.NumberPickerInputText">
<item name="android:textColor">@android:color/primary_text_light</item>
<item name="android:textSize">30sp</item>
@@ -1200,6 +1220,11 @@
<item name="android:textSize">18sp</item>
</style>
+ <!-- @hide -->
+ <style name="TextAppearance.Holo.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+ <item name="android:textColor">#505050</item>
+ </style>
+
<!-- Light text styles -->
<style name="TextAppearance.Holo.Light" parent="TextAppearance.Holo">
</style>
@@ -1296,6 +1321,10 @@
<item name="android:textSize">18sp</item>
</style>
+ <!-- @hide -->
+ <style name="TextAppearance.Holo.Light.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+ </style>
+
<!-- Widget Styles -->
<style name="Widget.Holo" parent="Widget">
@@ -1406,22 +1435,35 @@
<item name="android:listSelector">?android:attr/selectableItemBackground</item>
</style>
+ <!-- @hide -->
+ <style name="Widget.Holo.DayPickerWeekView">
+ <item name="android:selectionBackgroundColor">#330099FF</item>
+ <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
+ <item name="android:otherMonthDateColor">#66FFFFFF</item>
+ <item name="android:weekNumberColor">#33FFFFFF</item>
+ <item name="android:gridLinesColor">#19FFFFFF</item>
+ <item name="selectedDayLine">@android:drawable/simple_week_dayline_holo_light</item>
+ </style>
+
<style name="Widget.Holo.ImageButton" parent="Widget.ImageButton">
<item name="android:background">@android:drawable/btn_default_holo_dark</item>
</style>
+ <!-- @hide -->
<style name="Widget.Holo.ImageButton.NumberPickerUpButton">
<item name="android:background">@null</item>
<item name="android:paddingBottom">26sp</item>
<item name="android:src">@android:drawable/timepicker_up_btn_holo_dark</item>
</style>
+ <!-- @hide -->
<style name="Widget.Holo.ImageButton.NumberPickerDownButton">
<item name="android:background">@null</item>
<item name="android:paddingTop">26sp</item>
<item name="android:src">@android:drawable/timepicker_down_btn_holo_dark</item>
</style>
+ <!-- @hide -->
<style name="Widget.Holo.EditText.NumberPickerInputText">
<item name="android:paddingTop">13sp</item>
<item name="android:paddingBottom">13sp</item>
@@ -1767,14 +1809,21 @@
<item name="android:background">@android:drawable/btn_default_holo_light</item>
</style>
+ <!-- @hide -->
+ <style name="Widget.Holo.Light.DayPickerWeekView" parent="Widget.DayPickerWeekView">
+ </style>
+
+ <!-- @hide -->
<style name="Widget.Holo.Light.ImageButton.NumberPickerUpButton" parent="Widget.Holo.Light.ImageButton.NumberPickerUpButton">
<item name="android:background">@android:drawable/timepicker_up_btn_holo_light</item>
</style>
+ <!-- @hide -->
<style name="Widget.Holo.Light.ImageButton.NumberPickerDownButton" parent="Widget.Holo.ImageButton.NumberPickerDownButton">
<item name="android:background">@android:drawable/timepicker_down_btn_holo_light</item>
</style>
+ <!-- @hide -->
<style name="Widget.Holo.Light.EditText.NumberPickerInputText" parent="Widget.Holo.EditText.NumberPickerInputText">
</style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 0f21e9f..94e8f96 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -26,7 +26,7 @@
of it a dark color.
-->
<style name="Theme">
-
+
<item name="colorForeground">@android:color/bright_foreground_dark</item>
<item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
<item name="colorBackground">@android:color/background_dark</item>
@@ -280,6 +280,12 @@
<item name="numberPickerInputTextStyle">@style/Widget.EditText.NumberPickerInputText</item>
<item name="numberPickerStyle">@style/Widget.NumberPicker</item>
+ <!-- DayPicker$WeekView style-->
+ <item name="dayPickerWeekViewStyle">@style/Widget.DayPickerWeekView</item>
+
+ <!-- DayPickerWeekDayView style-->
+ <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Small.DayPickerWeekDayView</item>
+
</style>
<!-- Variant of the default (dark) theme with no title bar -->
@@ -917,6 +923,12 @@
<item name="numberPickerDownButtonStyle">@style/Widget.Holo.ImageButton.NumberPickerDownButton</item>
<item name="numberPickerInputTextStyle">@style/Widget.Holo.EditText.NumberPickerInputText</item>
+ <!-- DayPicker$WeekView style-->
+ <item name="dayPickerWeekViewStyle">@style/Widget.Holo.DayPickerWeekView</item>
+
+ <!-- DayPickerWeekDayView style-->
+ <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.DayPickerWeekDayView</item>
+
</style>
<!-- New Honeycomb holographic theme. Light version. The widgets in the
@@ -1162,6 +1174,12 @@
<item name="numberPickerDownButtonStyle">@style/Widget.Holo.Light.ImageButton.NumberPickerDownButton</item>
<item name="numberPickerInputTextStyle">@style/Widget.Holo.Light.EditText.NumberPickerInputText</item>
+ <!-- DayPicker$WeekView style-->
+ <item name="dayPickerWeekViewStyle">@style/Widget.Holo.Light.DayPickerWeekView</item>
+
+ <!-- DayPickerWeekDayView style-->
+ <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.Light.DayPickerWeekDayView</item>
+
</style>
<!-- Development legacy name; if you're using this, switch. -->
diff --git a/core/tests/ConnectivityManagerTest/Android.mk b/core/tests/ConnectivityManagerTest/Android.mk
index a1546fa..56011f7 100644
--- a/core/tests/ConnectivityManagerTest/Android.mk
+++ b/core/tests/ConnectivityManagerTest/Android.mk
@@ -25,6 +25,6 @@
LOCAL_PACKAGE_NAME := ConnectivityManagerTest
-#LOCAL_INSTRUMENTATION_FOR := connectivitymanagertest
+LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index b116bea..05f8b39 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -16,7 +16,8 @@
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.connectivitymanagertest">
+ package="com.android.connectivitymanagertest"
+ android:sharedUserId="com.android.uid.test">
<!-- We add an application tag here just so that we can indicate that
this package needs to link against the android.test library,
@@ -67,5 +68,9 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.DEVICE_POWER" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
</manifest>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
index 47f208a..5b76e39 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
@@ -19,8 +19,8 @@
import android.os.Bundle;
import android.test.InstrumentationTestRunner;
import android.test.InstrumentationTestSuite;
-import android.util.Log;
import com.android.connectivitymanagertest.stress.WifiApStress;
+import com.android.connectivitymanagertest.stress.WifiStressTest;
import junit.framework.TestSuite;
@@ -34,10 +34,18 @@
*/
public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunner {
+ public int mSoftapIterations = 100;
+ public int mScanIterations = 100;
+ public int mReconnectIterations = 100;
+ public int mSleepTime = 30 * 1000; // default sleep time is 30 seconds
+ public String mReconnectSsid = "securenetdhcp";
+ public String mReconnectPassword = "androidwifi";
+
@Override
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
suite.addTestSuite(WifiApStress.class);
+ suite.addTestSuite(WifiStressTest.class);
return suite;
}
@@ -49,14 +57,46 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- String stressValue = (String) icicle.get("stressnum");
- if (stressValue != null) {
- int iteration = Integer.parseInt(stressValue);
+ String valueStr = (String) icicle.get("softap_iterations");
+ if (valueStr != null) {
+ int iteration = Integer.parseInt(valueStr);
if (iteration > 0) {
- numStress = iteration;
+ mSoftapIterations = iteration;
+ }
+ }
+
+ String scanIterationStr = (String) icicle.get("scan_iterations");
+ if (scanIterationStr != null) {
+ int scanIteration = Integer.parseInt(scanIterationStr);
+ if (scanIteration > 0) {
+ mScanIterations = scanIteration;
+ }
+ }
+
+ String ssidStr= (String) icicle.get("reconnect_ssid");
+ if (ssidStr != null) {
+ mReconnectSsid = ssidStr;
+ }
+
+ String passwordStr = (String) icicle.get("reconnect_password");
+ if (passwordStr != null) {
+ mReconnectPassword = passwordStr;
+ }
+
+ String reconnectStr = (String) icicle.get("reconnect_iterations");
+ if (reconnectStr != null) {
+ int iteration = Integer.parseInt(reconnectStr);
+ if (iteration > 0) {
+ mReconnectIterations = iteration;
+ }
+ }
+
+ String sleepTimeStr = (String) icicle.get("sleep_time");
+ if (sleepTimeStr != null) {
+ int sleepTime = Integer.parseInt(sleepTimeStr);
+ if (sleepTime > 0) {
+ mSleepTime = 1000 * sleepTime;
}
}
}
-
- public int numStress = 100;
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 2888696..af74c6f 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -76,6 +76,7 @@
public String mBssid;
public String mPowerSsid = "GoogleGuest"; //Default power SSID
private Context mContext;
+ public boolean scanResultAvailable = false;
/*
* Control Wifi States
@@ -142,6 +143,7 @@
String action = intent.getAction();
Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+ log("scan results are available");
notifyScanResult();
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mWifiNetworkInfo =
@@ -174,6 +176,7 @@
public ConnectivityManagerTestActivity() {
mState = State.UNKNOWN;
+ scanResultAvailable = false;
}
@Override
@@ -267,6 +270,7 @@
private void notifyScanResult() {
synchronized (this) {
log("notify that scan results are available");
+ scanResultAvailable = true;
this.notify();
}
}
@@ -328,6 +332,8 @@
long startTime = System.currentTimeMillis();
while (true) {
if ((System.currentTimeMillis() - startTime) > timeout) {
+ log("waitForNetworkState time out, the state of network type " + networkType +
+ " is: " + mCM.getNetworkInfo(networkType).getState());
if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
return false;
} else {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index cc53ddc..21ab0e6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -19,25 +19,36 @@
import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
-import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
+import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiManager;
+import android.os.Environment;
+import android.os.PowerManager;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+
/**
* Stress the wifi driver as access point.
*/
public class WifiApStress
extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
private final static String TAG = "WifiApStress";
- private ConnectivityManagerTestActivity mAct;
private static String NETWORK_ID = "AndroidAPTest";
private static String PASSWD = "androidwifi";
- private int max_num;
+ private final static String OUTPUT_FILE = "WifiApStressOutput.txt";
+ private ConnectivityManagerTestActivity mAct;
+ private int iterations;
+ private PowerManager.WakeLock mWakelock = null;
+ private BufferedWriter mOutputWriter = null;
+ private int mLastIteration = 0;
public WifiApStress() {
super(ConnectivityManagerTestActivity.class);
@@ -47,11 +58,27 @@
public void setUp() throws Exception {
super.setUp();
mAct = getActivity();
- max_num = ((ConnectivityManagerStressTestRunner)getInstrumentation()).numStress;
+ ConnectivityManagerStressTestRunner mRunner =
+ (ConnectivityManagerStressTestRunner)getInstrumentation();
+ iterations = mRunner.mSoftapIterations;
+ PowerManager pm =
+ (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+ mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "wifiApStress");
+ mWakelock.acquire();
}
@Override
public void tearDown() throws Exception {
+ if (mWakelock != null) {
+ mWakelock.release();
+ }
+ // write the total number of iterations into output file
+ mOutputWriter = new BufferedWriter(new FileWriter(new File(
+ Environment.getExternalStorageDirectory(), OUTPUT_FILE)));
+ mOutputWriter.write(String.format("iteration %d out of %d"
+ + "\n", mLastIteration, iterations));
+ mOutputWriter.flush();
+ mOutputWriter.close();
super.tearDown();
}
@@ -67,15 +94,18 @@
if (mAct.mWifiManager.isWifiEnabled()) {
mAct.disableWifi();
}
- for (int i = 0; i < max_num; i++) {
+ int i;
+ for (i = 0; i < iterations; i++) {
Log.v(TAG, "iteration: " + i);
+ mLastIteration = i;
// enable Wifi tethering
assertTrue(mAct.mWifiManager.setWifiApEnabled(config, true));
// Wait for wifi ap state to be ENABLED
- assertTrue(mAct.waitForWifiAPState(mAct.mWifiManager.WIFI_AP_STATE_ENABLED,
- mAct.LONG_TIMEOUT));
+ assertTrue(mAct.waitForWifiAPState(WifiManager.WIFI_AP_STATE_ENABLED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// Wait for wifi tethering result
- assertEquals(mAct.SUCCESS, mAct.waitForTetherStateChange(2*mAct.SHORT_TIMEOUT));
+ assertEquals(ConnectivityManagerTestActivity.SUCCESS,
+ mAct.waitForTetherStateChange(2*ConnectivityManagerTestActivity.SHORT_TIMEOUT));
// Allow the wifi tethering to be enabled for 10 seconds
try {
Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
@@ -84,6 +114,9 @@
}
assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false));
}
+ if (i == iterations) {
+ mLastIteration = iterations;
+ }
}
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
new file mode 100644
index 0000000..0756a72
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.connectivitymanagertest.stress;
+
+import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
+import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo.State;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.IpAssignment;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.ProxySettings;
+import android.net.wifi.WifiManager;
+import android.os.Environment;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Stress Wi-Fi connection, scanning and reconnection after sleep.
+ *
+ * To run this stress test suite, type
+ * adb shell am instrument -e class com.android.connectivitymanagertest.stress.WifiStressTest
+ * -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
+ */
+public class WifiStressTest
+ extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+ private final static String TAG = "WifiStressTest";
+
+ /**
+ * Wi-Fi idle time for default sleep policy
+ */
+ private final static long WIFI_IDLE_MS = 5 * 1000;
+
+ /**
+ * The delay for Wi-Fi to get into idle, after screen off + WIFI_IDEL_MS + WIFI_IDLE_DELAY
+ * the Wi-Fi should be in idle mode and device should be in cellular mode.
+ */
+ private final static long WIFI_IDLE_DELAY = 3 * 1000;
+
+ private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
+ private ConnectivityManagerTestActivity mAct;
+ private int mReconnectIterations;
+ private int mWifiSleepTime;
+ private int mScanIterations;
+ private String mSsid;
+ private String mPassword;
+ private ConnectivityManagerStressTestRunner mRunner;
+ private PowerManager.WakeLock wl = null;
+ private BufferedWriter mOutputWriter = null;
+
+ public WifiStressTest() {
+ super(ConnectivityManagerTestActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mAct = getActivity();
+ mRunner = (ConnectivityManagerStressTestRunner) getInstrumentation();
+ mReconnectIterations = mRunner.mReconnectIterations;
+ mSsid = mRunner.mReconnectSsid;
+ mPassword = mRunner.mReconnectPassword;
+ mScanIterations = mRunner.mScanIterations;
+ mWifiSleepTime = mRunner.mSleepTime;
+ wl = null;
+ mOutputWriter = new BufferedWriter(new FileWriter(new File(
+ Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
+ if (!mAct.mWifiManager.isWifiEnabled()) {
+ if (!mAct.enableWifi()) {
+ tearDown();
+ fail("enable wifi failed.");
+ }
+ sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT,
+ "Interruped while waiting for wifi on");
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ log("tearDown()");
+ if ((wl != null) && wl.isHeld()) {
+ wl.release();
+ }
+ if (mOutputWriter != null) {
+ mOutputWriter.close();
+ }
+ super.tearDown();
+ }
+
+ private void writeOutput(String s) {
+ log("write message: " + s);
+ if (mOutputWriter == null) {
+ log("no writer attached to file " + OUTPUT_FILE);
+ return;
+ }
+ try {
+ mOutputWriter.write(s + "\n");
+ mOutputWriter.flush();
+ } catch (IOException e) {
+ log("failed to write output.");
+ }
+ }
+
+ private void turnScreenOff() {
+ log("Turn screen off");
+ if (wl != null) {
+ log("release wake lock");
+ wl.release();
+ }
+ PowerManager pm =
+ (PowerManager) mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+ pm.goToSleep(SystemClock.uptimeMillis() + 50);
+ }
+
+ private void turnScreenOn() {
+ log("Turn screen on");
+ PowerManager pm =
+ (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+ wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+ "wifiStressTest");
+ wl.acquire();
+ }
+
+ public void log(String message) {
+ Log.v(TAG, message);
+ }
+
+ private void sleep(long sometime, String errorMsg) {
+ try {
+ Thread.sleep(sometime);
+ } catch (InterruptedException e) {
+ fail(errorMsg);
+ }
+ }
+
+ /**
+ * Stress Wifi Scanning
+ * TODO: test the scanning quality for each frequency band
+ */
+ @LargeTest
+ public void testWifiScanning() {
+ int scanTimeSum = 0;
+ int i;
+ int averageScanTime = 0;
+ int ssidAppearInScanResultsCount = 0; // count times of given ssid appear in scan results.
+ for (i = 0; i < mScanIterations; i++) {
+ log("testWifiScanning: iteration: " + i);
+ writeOutput(String.format("scan iteration %d out of %d",
+ i, mScanIterations));
+ writeOutput(String.format("average scanning time is %d", averageScanTime));
+ writeOutput(String.format("ssid appear %d out of %d scan iterations",
+ ssidAppearInScanResultsCount, mScanIterations));
+ long startTime = System.currentTimeMillis();
+ mAct.scanResultAvailable = false;
+ assertTrue("start scan failed", mAct.mWifiManager.startScanActive());
+ while (true) {
+ if ((System.currentTimeMillis() - startTime) >
+ ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT) {
+ fail("Wifi scanning takes more than " +
+ ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT + " ms");
+ }
+ synchronized(mAct) {
+ try {
+ mAct.wait(ConnectivityManagerTestActivity.WAIT_FOR_SCAN_RESULT);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (mAct.scanResultAvailable) {
+ long scanTime = (System.currentTimeMillis() - startTime);
+ scanTimeSum += scanTime;
+ averageScanTime = scanTimeSum/mScanIterations;
+ log("average scanning time: " + averageScanTime);
+ break;
+ }
+ }
+ }
+ if ((mAct.mWifiManager.getScanResults() == null) ||
+ (mAct.mWifiManager.getScanResults().size() <= 0)) {
+ fail("Scan results are empty ");
+ }
+
+ List<ScanResult> netList = mAct.mWifiManager.getScanResults();
+ if (netList != null) {
+ log("size of scan result list: " + netList.size());
+ for (int s = 0; s < netList.size(); s++) {
+ ScanResult sr= netList.get(s);
+ log(String.format("scan result for %s is: %s", sr.SSID, sr.toString()));
+ log(String.format("signal level for %s is %d ", sr.SSID, sr.level));
+ if (sr.SSID.equals(mSsid)) {
+ ssidAppearInScanResultsCount += 1;
+ log("Number of times " + mSsid + " appear in the scan list: " +
+ ssidAppearInScanResultsCount);
+ break;
+ }
+ }
+ }
+ }
+ if (i == mScanIterations) {
+ writeOutput(String.format("scan iteration %d out of %d",
+ i, mScanIterations));
+ writeOutput(String.format("average scanning time is %d", averageScanTime));
+ writeOutput(String.format("ssid appear %d out of %d scan iterations",
+ ssidAppearInScanResultsCount, mScanIterations));
+ }
+ }
+
+ // Stress Wifi reconnection to secure net after sleep
+ @LargeTest
+ public void testWifiReconnectionAfterSleep() {
+ int value = Settings.System.getInt(mRunner.getContext().getContentResolver(),
+ Settings.System.WIFI_SLEEP_POLICY, -1);
+ if (value < 0) {
+ Settings.System.putInt(mRunner.getContext().getContentResolver(),
+ Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
+ log("set wifi sleep policy to default value");
+ }
+ Settings.Secure.putLong(mRunner.getContext().getContentResolver(),
+ Settings.Secure.WIFI_IDLE_MS, WIFI_IDLE_MS);
+
+ // Connect to a Wi-Fi network
+ turnScreenOn();
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = mSsid;
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ if (mPassword.matches("[0-9A-Fa-f]{64}")) {
+ config.preSharedKey = mPassword;
+ } else {
+ config.preSharedKey = '"' + mPassword + '"';
+ }
+ config.ipAssignment = IpAssignment.DHCP;
+ config.proxySettings = ProxySettings.NONE;
+
+ assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
+ mAct.connectToWifiWithConfiguration(config));
+ assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+ ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+ assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ int i;
+ for (i = 0; i < mReconnectIterations; i++) {
+ // 1. Put device into sleep
+ // 2. Wait for the device to sleep for sometime, very 3G is connected
+ // 3. Wake up the device
+ writeOutput(String.format("reconnection after sleep iteration %d out of %d",
+ i, mReconnectIterations));
+ log("iteration: " + i);
+ turnScreenOff();
+ PowerManager pm =
+ (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+ assertFalse(pm.isScreenOn());
+ sleep(WIFI_IDLE_MS + WIFI_IDLE_DELAY, "Interruped while wait for wifi to be idle");
+ assertTrue("Wait for Wi-Fi to idle timeout",
+ mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+ assertTrue("Wait for cellular connection timeout",
+ mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ sleep(mWifiSleepTime + WIFI_IDLE_DELAY, "Interrupted while device is in sleep mode");
+ // Turn screen on again
+ turnScreenOn();
+ assertTrue("Wait for Wi-Fi enable timeout after wake up",
+ mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+ ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+ assertTrue("Wait for Wi-Fi connection timeout after wake up",
+ mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ }
+ if (i == mReconnectIterations) {
+ writeOutput(String.format("reconnection after sleep iteration %d out of %d",
+ i, mReconnectIterations));
+ }
+ }
+}
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 8450c3a..66f8f70 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -210,7 +210,6 @@
* expense of the decoding speed. Currently the field only affects JPEG
* decode, in the case of which a more accurate, but slightly slower,
* IDCT method will be used instead.
- * @hide
*/
public boolean inPreferQualityOverSpeed;
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index 6291124..4b698e6 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -22,6 +22,7 @@
namespace android {
+struct AMessage;
struct IMemory;
struct IStreamListener;
@@ -38,13 +39,14 @@
DECLARE_META_INTERFACE(StreamListener);
enum Command {
- FLUSH,
+ EOS,
DISCONTINUITY,
- EOS
};
virtual void queueBuffer(size_t index, size_t size) = 0;
- virtual void queueCommand(Command cmd) = 0;
+
+ virtual void issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
};
////////////////////////////////////////////////////////////////////////////////
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index c674cba..2fbdddc 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -26,10 +26,14 @@
namespace android {
struct AString;
+struct Parcel;
struct AMessage : public RefBase {
AMessage(uint32_t what = 0, ALooper::handler_id target = 0);
+ static sp<AMessage> FromParcel(const Parcel &parcel);
+ void writeToParcel(Parcel *parcel) const;
+
void setWhat(uint32_t what);
uint32_t what() const;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index fc14777..1a89ca0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -954,11 +954,11 @@
mSnapshot->region && mesh->hasEmptyQuads) {
const size_t count = mesh->quads.size();
for (size_t i = 0; i < count; i++) {
- Rect bounds = mesh->quads.itemAt(i);
+ const Rect& bounds = mesh->quads.itemAt(i);
if (pureTranslate) {
const float x = (int) floorf(bounds.left + 0.5f);
const float y = (int) floorf(bounds.top + 0.5f);
- dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getBottom(),
+ dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
*mSnapshot->transform);
} else {
dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 17b1d86..e5cb67b 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -35,7 +35,7 @@
mXCount(xCount), mYCount(yCount), mEmptyQuads(emptyQuads) {
// Initialized with the maximum number of vertices we will need
// 2 triangles per patch, 3 vertices per triangle
- const int maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
+ uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
mVertices = new TextureVertex[maxVertices];
mUploaded = false;
@@ -160,7 +160,7 @@
float y2 = 0.0f;
if (i & 1) {
const float segment = stepY - previousStepY;
- y2 = y1 + segment * stretchY;
+ y2 = y1 + floorf(segment * stretchY + 0.5f);
} else {
y2 = y1 + stepY - previousStepY;
}
@@ -206,7 +206,7 @@
float x2 = 0.0f;
if (i & 1) {
const float segment = stepX - previousStepX;
- x2 = x1 + segment * stretchX;
+ x2 = x1 + floorf(segment * stretchX + 0.5f);
} else {
x2 = x1 + stepX - previousStepX;
}
@@ -226,7 +226,7 @@
void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
float u1, float v1, float u2, float v2, uint32_t& quadCount) {
const uint32_t oldQuadCount = quadCount;
- const bool valid = fabs(x2 - x1) > 0.9999f && fabs(y2 - y1) > 0.9999f;
+ const bool valid = x2 - x1 > 0.9999f && y2 - y1 > 0.9999f;
if (valid) {
quadCount++;
}
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 16ad86d..0f0ffa2 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -52,9 +52,7 @@
GLuint meshBuffer;
uint32_t verticesCount;
bool hasEmptyQuads;
-#if RENDER_LAYERS_AS_REGIONS
Vector<Rect> quads;
-#endif
private:
TextureVertex* mVertices;
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 6587b51..d4edafd 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -378,6 +378,12 @@
static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name) {
const ScriptCState::SymbolTable_t *sym;
ScriptC *s = (ScriptC *)pContext;
+ if (!strcmp(name, "__isThreadable")) {
+ return (BCCvoid*) s->mEnviroment.mIsThreadable;
+ } else if (!strcmp(name, "__clearThreadable")) {
+ s->mEnviroment.mIsThreadable = false;
+ return NULL;
+ }
sym = ScriptCState::lookupSymbol(name);
if (!sym) {
sym = ScriptCState::lookupSymbolCL(name);
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index d3a71b3..d539833 100755
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -28,6 +28,8 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.R;
+
/**
* A GPS Network-initiated Handler class used by LocationManager.
*
@@ -182,8 +184,8 @@
return;
}
- String title = getNotifTitle(notif);
- String message = getNotifMessage(notif);
+ String title = getNotifTitle(notif, mContext);
+ String message = getNotifMessage(notif, mContext);
if (DEBUG) Log.d(TAG, "setNiNotification, notifyId: " + notif.notificationId +
", title: " + title +
@@ -203,7 +205,7 @@
}
mNiNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mNiNotification.tickerText = getNotifTicker(notif);
+ mNiNotification.tickerText = getNotifTicker(notif, mContext);
// if not to popup dialog immediately, pending intent will open the dialog
Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
@@ -234,8 +236,8 @@
private Intent getDlgIntent(GpsNiNotification notif)
{
Intent intent = new Intent();
- String title = getDialogTitle(notif);
- String message = getDialogMessage(notif);
+ String title = getDialogTitle(notif, mContext);
+ String message = getDialogMessage(notif, mContext);
// directly bring up the NI activity
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -412,41 +414,40 @@
}
// change this to configure notification display
- static private String getNotifTicker(GpsNiNotification notif)
+ static private String getNotifTicker(GpsNiNotification notif, Context context)
{
- String ticker = String.format("Position request! ReqId: [%s] ClientName: [%s]",
+ String ticker = String.format(context.getString(R.string.gpsNotifTicker),
decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
decodeString(notif.text, mIsHexInput, notif.textEncoding));
return ticker;
}
// change this to configure notification display
- static private String getNotifTitle(GpsNiNotification notif)
+ static private String getNotifTitle(GpsNiNotification notif, Context context)
{
- String title = String.format("Position Request");
+ String title = String.format(context.getString(R.string.gpsNotifTitle));
return title;
}
// change this to configure notification display
- static private String getNotifMessage(GpsNiNotification notif)
+ static private String getNotifMessage(GpsNiNotification notif, Context context)
{
- String message = String.format(
- "NI Request received from [%s] for client [%s]!",
+ String message = String.format(context.getString(R.string.gpsNotifMessage),
decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
decodeString(notif.text, mIsHexInput, notif.textEncoding));
return message;
}
// change this to configure dialog display (for verification)
- static public String getDialogTitle(GpsNiNotification notif)
+ static public String getDialogTitle(GpsNiNotification notif, Context context)
{
- return getNotifTitle(notif);
+ return getNotifTitle(notif, context);
}
// change this to configure dialog display (for verification)
- static private String getDialogMessage(GpsNiNotification notif)
+ static private String getDialogMessage(GpsNiNotification notif, Context context)
{
- return getNotifMessage(notif);
+ return getNotifMessage(notif, context);
}
}
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 731c09d..74fb531 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -36,7 +36,8 @@
fixedfft.cpp.arm
LOCAL_SHARED_LIBRARIES := \
- libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
+ libui libcutils libutils libbinder libsonivox libicuuc libexpat \
+ libsurfaceflinger_client libcamera_client libstagefright_foundation
LOCAL_MODULE:= libmedia
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index 89f2b44..5069002 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <media/IStreamSource.h>
+#include <media/stagefright/foundation/AMessage.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
@@ -33,7 +34,7 @@
// IStreamListener
QUEUE_BUFFER,
- QUEUE_COMMAND,
+ ISSUE_COMMAND,
};
struct BpStreamSource : public BpInterface<IStreamSource> {
@@ -125,12 +126,21 @@
remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
}
- virtual void queueCommand(Command cmd) {
+ virtual void issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &msg) {
Parcel data, reply;
data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor());
data.writeInt32(static_cast<int32_t>(cmd));
+ data.writeInt32(static_cast<int32_t>(synchronous));
- remote()->transact(QUEUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY);
+ if (msg != NULL) {
+ data.writeInt32(1);
+ msg->writeToParcel(&data);
+ } else {
+ data.writeInt32(0);
+ }
+
+ remote()->transact(ISSUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -149,12 +159,20 @@
break;
}
- case QUEUE_COMMAND:
+ case ISSUE_COMMAND:
{
CHECK_INTERFACE(IStreamListener, data, reply);
Command cmd = static_cast<Command>(data.readInt32());
- queueCommand(cmd);
+ bool synchronous = static_cast<bool>(data.readInt32());
+
+ sp<AMessage> msg;
+
+ if (data.readInt32()) {
+ msg = AMessage::FromParcel(data);
+ }
+
+ issueCommand(cmd, synchronous, msg);
break;
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 2743a3a..7613d04 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -50,6 +50,7 @@
#include <surfaceflinger/Surface.h>
#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
#include "include/LiveSession.h"
#define USE_SURFACE_ALLOC 1
@@ -170,7 +171,9 @@
void clearOwner();
virtual void queueBuffer(size_t index, size_t size);
- virtual void queueCommand(Command cmd);
+
+ virtual void issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &msg);
private:
Mutex mLock;
@@ -188,7 +191,11 @@
virtual ssize_t readAt(off64_t offset, void *data, size_t size);
virtual void queueBuffer(size_t index, size_t size);
- virtual void queueCommand(IStreamListener::Command cmd);
+
+ virtual void issueCommand(
+ IStreamListener::Command cmd,
+ bool synchronous,
+ const sp<AMessage> &msg);
protected:
virtual ~QueueDataSource();
@@ -198,7 +205,12 @@
kNumBuffers = 16
};
- struct BufferInfo {
+ struct QueueEntry {
+ bool mIsCommand;
+
+ IStreamListener::Command mCommand;
+ sp<AMessage> mCommandMessage;
+
size_t mIndex;
size_t mOffset;
size_t mSize;
@@ -212,7 +224,7 @@
sp<MemoryDealer> mDealer;
Vector<sp<IMemory> > mBuffers;
- List<BufferInfo> mFilledBuffers;
+ List<QueueEntry> mQueue;
off64_t mPosition;
bool mEOS;
@@ -227,7 +239,7 @@
mListener = new QueueListener(this);
mSource->setListener(mListener);
- static const size_t kBufferSize = 8192;
+ static const size_t kBufferSize = (8192 / 188) * 188;
mDealer = new MemoryDealer(kNumBuffers * kBufferSize);
for (size_t i = 0; i < kNumBuffers; ++i) {
@@ -246,10 +258,6 @@
QueueDataSource::~QueueDataSource() {
Mutex::Autolock autoLock(mLock);
- while (mFilledBuffers.size() < kNumBuffers && !mEOS) {
- mCondition.wait(mLock);
- }
-
mListener->clearOwner();
}
@@ -264,40 +272,69 @@
Mutex::Autolock autoLock(mLock);
+ if (mEOS) {
+ return ERROR_END_OF_STREAM;
+ }
+
size_t sizeDone = 0;
while (sizeDone < size) {
- while (mFilledBuffers.empty() && !mEOS) {
+ while (mQueue.empty()) {
mCondition.wait(mLock);
}
- if (mFilledBuffers.empty()) {
- if (sizeDone > 0) {
- mPosition += sizeDone;
- return sizeDone;
+ QueueEntry &entry = *mQueue.begin();
+
+ if (entry.mIsCommand) {
+ switch (entry.mCommand) {
+ case IStreamListener::EOS:
+ {
+ mEOS = true;
+
+ if (sizeDone > 0) {
+ offset += sizeDone;
+ return sizeDone;
+ } else {
+ return ERROR_END_OF_STREAM;
+ }
+ break;
+ }
+
+ case IStreamListener::DISCONTINUITY:
+ {
+ CHECK_EQ(size, 188u);
+ CHECK_EQ(sizeDone, 0u);
+
+ memset(data, 0, size);
+ sizeDone = size;
+ break;
+ }
+
+ default:
+ break;
}
- return ERROR_END_OF_STREAM;
+
+ mQueue.erase(mQueue.begin());
+ continue;
}
- BufferInfo &info = *mFilledBuffers.begin();
-
size_t copy = size - sizeDone;
- if (copy > info.mSize) {
- copy = info.mSize;
+ if (copy > entry.mSize) {
+ copy = entry.mSize;
}
memcpy((uint8_t *)data + sizeDone,
- (const uint8_t *)mBuffers.itemAt(info.mIndex)->pointer()
- + info.mOffset,
+ (const uint8_t *)mBuffers.itemAt(entry.mIndex)->pointer()
+ + entry.mOffset,
copy);
- info.mSize -= copy;
- info.mOffset += copy;
+ entry.mSize -= copy;
+ entry.mOffset += copy;
sizeDone += copy;
- if (info.mSize == 0) {
- mSource->onBufferAvailable(info.mIndex);
- mFilledBuffers.erase(mFilledBuffers.begin());
+ if (entry.mSize == 0) {
+ mSource->onBufferAvailable(entry.mIndex);
+ mQueue.erase(mQueue.begin());
}
}
@@ -312,22 +349,31 @@
CHECK_LT(index, mBuffers.size());
CHECK_LE(size, mBuffers.itemAt(index)->size());
- BufferInfo info;
- info.mIndex = index;
- info.mSize = size;
- info.mOffset = 0;
+ QueueEntry entry;
+ entry.mIsCommand = false;
+ entry.mIndex = index;
+ entry.mSize = size;
+ entry.mOffset = 0;
- mFilledBuffers.push_back(info);
+ mQueue.push_back(entry);
mCondition.signal();
}
-void QueueDataSource::queueCommand(IStreamListener::Command cmd) {
+void QueueDataSource::issueCommand(
+ IStreamListener::Command cmd,
+ bool synchronous,
+ const sp<AMessage> &msg) {
Mutex::Autolock autoLock(mLock);
- if (cmd == IStreamListener::EOS) {
- mEOS = true;
- mCondition.signal();
- }
+ CHECK(!synchronous);
+
+ QueueEntry entry;
+ entry.mIsCommand = true;
+ entry.mCommand = cmd;
+ entry.mCommandMessage = msg;
+ mQueue.push_back(entry);
+
+ mCondition.signal();
}
void QueueListener::clearOwner() {
@@ -343,12 +389,13 @@
mOwner->queueBuffer(index, size);
}
-void QueueListener::queueCommand(Command cmd) {
+void QueueListener::issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &msg) {
Mutex::Autolock autoLock(mLock);
if (mOwner == NULL) {
return;
}
- mOwner->queueCommand(cmd);
+ mOwner->issueCommand(cmd, synchronous, msg);
}
////////////////////////////////////////////////////////////////////////////////
@@ -469,18 +516,9 @@
reset_l();
sp<DataSource> dataSource = new QueueDataSource(source);
-
-#if 0
- sp<MediaExtractor> extractor =
- MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+ sp<MediaExtractor> extractor = new MPEG2TSExtractor(dataSource);
return setDataSource_l(extractor);
-#else
- sp<NuCachedSource2> cached = new NuCachedSource2(dataSource);
- dataSource = cached;
-
- return setDataSource_l(dataSource);
-#endif
}
status_t AwesomePlayer::setDataSource_l(
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 26c6d42..7da9cb8 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -23,6 +23,8 @@
#include "ALooperRoster.h"
#include "AString.h"
+#include <binder/Parcel.h>
+
namespace android {
AMessage::AMessage(uint32_t what, ALooper::handler_id target)
@@ -341,4 +343,136 @@
return s;
}
+// static
+sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
+ int32_t what = parcel.readInt32();
+ sp<AMessage> msg = new AMessage(what);
+
+ msg->mNumItems = static_cast<size_t>(parcel.readInt32());
+
+ for (size_t i = 0; i < msg->mNumItems; ++i) {
+ Item *item = &msg->mItems[i];
+
+ item->mName = AAtomizer::Atomize(parcel.readCString());
+ item->mType = static_cast<Type>(parcel.readInt32());
+
+ switch (item->mType) {
+ case kTypeInt32:
+ {
+ item->u.int32Value = parcel.readInt32();
+ break;
+ }
+
+ case kTypeInt64:
+ {
+ item->u.int64Value = parcel.readInt64();
+ break;
+ }
+
+ case kTypeSize:
+ {
+ item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
+ break;
+ }
+
+ case kTypeFloat:
+ {
+ item->u.floatValue = parcel.readFloat();
+ break;
+ }
+
+ case kTypeDouble:
+ {
+ item->u.doubleValue = parcel.readDouble();
+ break;
+ }
+
+ case kTypeString:
+ {
+ item->u.stringValue = new AString(parcel.readCString());
+ break;
+ }
+
+ case kTypeMessage:
+ {
+ sp<AMessage> subMsg = AMessage::FromParcel(parcel);
+ subMsg->incStrong(msg.get());
+
+ item->u.refValue = subMsg.get();
+ break;
+ }
+
+ default:
+ {
+ LOGE("This type of object cannot cross process boundaries.");
+ TRESPASS();
+ }
+ }
+ }
+
+ return msg;
+}
+
+void AMessage::writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32(static_cast<int32_t>(mWhat));
+ parcel->writeInt32(static_cast<int32_t>(mNumItems));
+
+ for (size_t i = 0; i < mNumItems; ++i) {
+ const Item &item = mItems[i];
+
+ parcel->writeCString(item.mName);
+ parcel->writeInt32(static_cast<int32_t>(item.mType));
+
+ switch (item.mType) {
+ case kTypeInt32:
+ {
+ parcel->writeInt32(item.u.int32Value);
+ break;
+ }
+
+ case kTypeInt64:
+ {
+ parcel->writeInt64(item.u.int64Value);
+ break;
+ }
+
+ case kTypeSize:
+ {
+ parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
+ break;
+ }
+
+ case kTypeFloat:
+ {
+ parcel->writeFloat(item.u.floatValue);
+ break;
+ }
+
+ case kTypeDouble:
+ {
+ parcel->writeDouble(item.u.doubleValue);
+ break;
+ }
+
+ case kTypeString:
+ {
+ parcel->writeCString(item.u.stringValue->c_str());
+ break;
+ }
+
+ case kTypeMessage:
+ {
+ static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
+ break;
+ }
+
+ default:
+ {
+ LOGE("This type of object cannot cross process boundaries.");
+ TRESPASS();
+ }
+ }
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index ffa7db0..a4d4809 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -18,14 +18,7 @@
LOCAL_SHARED_LIBRARIES := \
libbinder \
- libmedia \
libutils \
- libcutils \
- libui \
- libsonivox \
- libvorbisidec \
- libsurfaceflinger_client \
- libcamera_client
LOCAL_CFLAGS += -Wno-multichar
diff --git a/opengl/java/android/opengl/ETC1.java b/opengl/java/android/opengl/ETC1.java
index f3dac77..fb5f9b4 100644
--- a/opengl/java/android/opengl/ETC1.java
+++ b/opengl/java/android/opengl/ETC1.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2009 Google Inc.
+ * Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/opengl/java/android/opengl/ETC1Util.java b/opengl/java/android/opengl/ETC1Util.java
index dd28d1d..3629d41 100644
--- a/opengl/java/android/opengl/ETC1Util.java
+++ b/opengl/java/android/opengl/ETC1Util.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2009 Google Inc.
+ * Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
diff --git a/opengl/java/android/opengl/GLES10.java b/opengl/java/android/opengl/GLES10.java
index 790acbd..7c0f949 100644
--- a/opengl/java/android/opengl/GLES10.java
+++ b/opengl/java/android/opengl/GLES10.java
@@ -1,19 +1,18 @@
/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
// This source file is automatically generated
diff --git a/opengl/java/android/opengl/GLES10Ext.java b/opengl/java/android/opengl/GLES10Ext.java
index 81fc59e..116ab9d 100644
--- a/opengl/java/android/opengl/GLES10Ext.java
+++ b/opengl/java/android/opengl/GLES10Ext.java
@@ -1,19 +1,18 @@
/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
// This source file is automatically generated
diff --git a/opengl/java/android/opengl/GLES11.java b/opengl/java/android/opengl/GLES11.java
index 1ca179b..b24c043 100644
--- a/opengl/java/android/opengl/GLES11.java
+++ b/opengl/java/android/opengl/GLES11.java
@@ -1,19 +1,18 @@
/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
// This source file is automatically generated
diff --git a/opengl/java/android/opengl/GLES11Ext.java b/opengl/java/android/opengl/GLES11Ext.java
index 25d5467..a9a7a22 100644
--- a/opengl/java/android/opengl/GLES11Ext.java
+++ b/opengl/java/android/opengl/GLES11Ext.java
@@ -1,19 +1,18 @@
/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
// This source file is automatically generated
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index 635f811..700164b 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -1,19 +1,18 @@
/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
// This source file is automatically generated
diff --git a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
index b03392e..c2f4400 100644
--- a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
index f10c02f..9cf5de7 100644
--- a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
index 6321632..cb94888 100644
--- a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 3e06ded..8a7124d 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -1,19 +1,18 @@
/*
-**
-** Copyright 2006, 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.
-*/
+ * Copyright (C) 2006 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.google.android.gles_jni;
diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
index 66cc200..f6b90ab 100644
--- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.google.android.gles_jni;
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 090c0cb7..50f6760 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -1,19 +1,18 @@
-/* //device/java/android/com/google/android/gles_jni/GLImpl.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.
+ */
// This source file is automatically generated
diff --git a/opengl/java/javax/microedition/khronos/egl/EGL.java b/opengl/java/javax/microedition/khronos/egl/EGL.java
index b743968..18f8ae6 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGL.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGL.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLConfig.java b/opengl/java/javax/microedition/khronos/egl/EGLConfig.java
index a1e496c..c8a9ba2 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLConfig.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLConfig.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLContext.java b/opengl/java/javax/microedition/khronos/egl/EGLContext.java
index fc94492..f8d745d 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLContext.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLContext.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java b/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java
index cd8a755..5368b4b 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLDisplay.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
diff --git a/opengl/java/javax/microedition/khronos/egl/EGLSurface.java b/opengl/java/javax/microedition/khronos/egl/EGLSurface.java
index 5349bc1..e1d08d3 100644
--- a/opengl/java/javax/microedition/khronos/egl/EGLSurface.java
+++ b/opengl/java/javax/microedition/khronos/egl/EGLSurface.java
@@ -1,19 +1,18 @@
-/*
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.egl;
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL.java b/opengl/java/javax/microedition/khronos/opengles/GL.java
index 3b78f3d..d5b60c6 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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 javax.microedition.khronos.opengles;
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10.java b/opengl/java/javax/microedition/khronos/opengles/GL10.java
index 4fcfb52..f48ecde 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL10.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL10.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL10.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.
+ */
// This source file is automatically generated
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
index 562b20a..f3252ab 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL10Ext.java
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
// This source file is automatically generated
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11.java b/opengl/java/javax/microedition/khronos/opengles/GL11.java
index 3ba110c..943a5be 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL11.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.
+ */
// This source file is automatically generated
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
index 459a1ab..842db7a 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL11Ext.java
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
// This source file is automatically generated
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
index 933c91e..97d5fd8 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
@@ -1,19 +1,18 @@
-/* //device/java/android/javax/microedition/khronos/opengles/GL11ExtensionPack.java
-**
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
// This source file is automatically generated
diff --git a/opengl/tests/gl2_java/AndroidManifest.xml b/opengl/tests/gl2_java/AndroidManifest.xml
index 585b63f1..8bb6840 100644
--- a/opengl/tests/gl2_java/AndroidManifest.xml
+++ b/opengl/tests/gl2_java/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl2_java/res/values/strings.xml b/opengl/tests/gl2_java/res/values/strings.xml
index d718b1d..06bd23c 100644
--- a/opengl/tests/gl2_java/res/values/strings.xml
+++ b/opengl/tests/gl2_java/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl2_jni/AndroidManifest.xml b/opengl/tests/gl2_jni/AndroidManifest.xml
index a72a6a5..1827e5f 100644
--- a/opengl/tests/gl2_jni/AndroidManifest.xml
+++ b/opengl/tests/gl2_jni/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl2_jni/res/values/strings.xml b/opengl/tests/gl2_jni/res/values/strings.xml
index e3f7331..a29c74b 100644
--- a/opengl/tests/gl2_jni/res/values/strings.xml
+++ b/opengl/tests/gl2_jni/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl_jni/AndroidManifest.xml b/opengl/tests/gl_jni/AndroidManifest.xml
index 64bd6bf..5d0ec96 100644
--- a/opengl/tests/gl_jni/AndroidManifest.xml
+++ b/opengl/tests/gl_jni/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl_jni/res/values/strings.xml b/opengl/tests/gl_jni/res/values/strings.xml
index 880f5c9..aee9fa0 100644
--- a/opengl/tests/gl_jni/res/values/strings.xml
+++ b/opengl/tests/gl_jni/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gl_perfapp/AndroidManifest.xml b/opengl/tests/gl_perfapp/AndroidManifest.xml
index 305d95f..ee4bd98 100644
--- a/opengl/tests/gl_perfapp/AndroidManifest.xml
+++ b/opengl/tests/gl_perfapp/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gl_perfapp/res/values/strings.xml b/opengl/tests/gl_perfapp/res/values/strings.xml
index dc21075..52cd961 100644
--- a/opengl/tests/gl_perfapp/res/values/strings.xml
+++ b/opengl/tests/gl_perfapp/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/gldual/AndroidManifest.xml b/opengl/tests/gldual/AndroidManifest.xml
index 06f4c4d..a36f4f7 100644
--- a/opengl/tests/gldual/AndroidManifest.xml
+++ b/opengl/tests/gldual/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/gldual/res/values/strings.xml b/opengl/tests/gldual/res/values/strings.xml
index 4267dff..b1f535d 100644
--- a/opengl/tests/gldual/res/values/strings.xml
+++ b/opengl/tests/gldual/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testFramerate/AndroidManifest.xml b/opengl/tests/testFramerate/AndroidManifest.xml
index e04342c..85617f4 100644
--- a/opengl/tests/testFramerate/AndroidManifest.xml
+++ b/opengl/tests/testFramerate/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testFramerate/res/values/strings.xml b/opengl/tests/testFramerate/res/values/strings.xml
index e6b3088..baadf0e 100644
--- a/opengl/tests/testFramerate/res/values/strings.xml
+++ b/opengl/tests/testFramerate/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testLatency/AndroidManifest.xml b/opengl/tests/testLatency/AndroidManifest.xml
index 741266e..59f2643 100644
--- a/opengl/tests/testLatency/AndroidManifest.xml
+++ b/opengl/tests/testLatency/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testLatency/res/values/strings.xml b/opengl/tests/testLatency/res/values/strings.xml
index 0309991..d80b77c 100644
--- a/opengl/tests/testLatency/res/values/strings.xml
+++ b/opengl/tests/testLatency/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testPauseResume/AndroidManifest.xml b/opengl/tests/testPauseResume/AndroidManifest.xml
index 3e8e7e7..1879bc3 100644
--- a/opengl/tests/testPauseResume/AndroidManifest.xml
+++ b/opengl/tests/testPauseResume/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testPauseResume/res/values/strings.xml b/opengl/tests/testPauseResume/res/values/strings.xml
index 208fe15..b4c98fe2 100644
--- a/opengl/tests/testPauseResume/res/values/strings.xml
+++ b/opengl/tests/testPauseResume/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tests/testViewport/AndroidManifest.xml b/opengl/tests/testViewport/AndroidManifest.xml
index 90a9d2d..ba178bb 100644
--- a/opengl/tests/testViewport/AndroidManifest.xml
+++ b/opengl/tests/testViewport/AndroidManifest.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/opengl/tests/testViewport/res/values/strings.xml b/opengl/tests/testViewport/res/values/strings.xml
index f4b8bbb..c037a7c 100644
--- a/opengl/tests/testViewport/res/values/strings.xml
+++ b/opengl/tests/testViewport/res/values/strings.xml
@@ -1,21 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2006, 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.
-*/
+<!-- Copyright (C) 2006 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.
-->
<!-- This file contains resource definitions for displayed strings, allowing
diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.java b/opengl/tools/glgen/stubs/gles11/glGetString.java
index d44a6dd..b02a0d1 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetString.java
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.java
@@ -1,21 +1,21 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- // C function const GLubyte * glGetString ( GLenum name )
-
- public static native String glGetString(
- int name
- );
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ // C function const GLubyte * glGetString ( GLenum name )
+
+ public static native String glGetString(
+ int name
+ );
diff --git a/packages/DefaultContainerService/Android.mk b/packages/DefaultContainerService/Android.mk
index 986b6c8..56b8005 100755
--- a/packages/DefaultContainerService/Android.mk
+++ b/packages/DefaultContainerService/Android.mk
@@ -7,7 +7,7 @@
LOCAL_PACKAGE_NAME := DefaultContainerService
-LOCAL_JNI_SHARED_LIBRARIES := libdefcontainer_jni
+LOCAL_REQUIRED_MODULES := libdefcontainer_jni
LOCAL_CERTIFICATE := platform
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 535f07f..f1fa0ff 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1015,7 +1015,10 @@
sp<Client> client = getClientFromCookie(user);
if (client == 0) return;
- if (!client->lockIfMessageWanted(msgType)) return;
+ if (!client->lockIfMessageWanted(msgType)) {
+ client->releaseRecordingFrame(dataPtr);
+ return;
+ }
if (dataPtr == 0) {
LOGE("Null data returned in data with timestamp callback");
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index f1fce3e..9d11d87 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
+import android.net.DummyDataStateTracker;
import android.net.IConnectivityManager;
import android.net.MobileDataStateTracker;
import android.net.NetworkInfo;
@@ -386,7 +387,6 @@
* the number of different network types is not going
* to change very often.
*/
- boolean noMobileData = !getMobileDataEnabled();
for (int netType : mPriorityList) {
switch (mNetAttributes[netType].mRadio) {
case ConnectivityManager.TYPE_WIFI:
@@ -406,10 +406,11 @@
mNetTrackers[netType] = new MobileDataStateTracker(netType,
mNetAttributes[netType].mName);
mNetTrackers[netType].startMonitoring(context, mHandler);
- if (noMobileData) {
- if (DBG) log("tearing down Mobile networks due to setting");
- mNetTrackers[netType].teardown();
- }
+ break;
+ case ConnectivityManager.TYPE_DUMMY:
+ mNetTrackers[netType] = new DummyDataStateTracker(netType,
+ mNetAttributes[netType].mName);
+ mNetTrackers[netType].startMonitoring(context, mHandler);
break;
default:
loge("Trying to create a DataStateTracker for an unknown radio type " +
@@ -685,10 +686,6 @@
// TODO - move this into the MobileDataStateTracker
int usedNetworkType = networkType;
if(networkType == ConnectivityManager.TYPE_MOBILE) {
- if (!getMobileDataEnabled()) {
- if (DBG) log("requested special network with data disabled - rejected");
- return Phone.APN_TYPE_NOT_AVAILABLE;
- }
if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
@@ -979,6 +976,9 @@
* @see ConnectivityManager#getMobileDataEnabled()
*/
public boolean getMobileDataEnabled() {
+ // TODO: This detail should probably be in DataConnectionTracker's
+ // which is where we store the value and maybe make this
+ // asynchronous.
enforceAccessPermission();
boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.MOBILE_DATA, 1) == 1;
@@ -998,42 +998,14 @@
}
private void handleSetMobileData(boolean enabled) {
- if (getMobileDataEnabled() == enabled) return;
-
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
-
- if (enabled) {
- if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
- if (DBG) {
- log("starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
- }
- mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
+ if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
+ if (DBG) {
+ Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
}
- } else {
- for (NetworkStateTracker nt : mNetTrackers) {
- if (nt == null) continue;
- int netType = nt.getNetworkInfo().getType();
- if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) {
- if (DBG) log("tearing down " + nt);
- nt.teardown();
- }
- }
+ mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
}
}
- private int getNumConnectedNetworks() {
- int numConnectedNets = 0;
-
- for (NetworkStateTracker nt : mNetTrackers) {
- if (nt != null && nt.getNetworkInfo().isConnected() &&
- !nt.isTeardownRequested()) {
- ++numConnectedNets;
- }
- }
- return numConnectedNets;
- }
-
private void enforceAccessPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -1153,16 +1125,9 @@
int newType = -1;
int newPriority = -1;
- boolean noMobileData = !getMobileDataEnabled();
for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
if (checkType == prevNetType) continue;
if (mNetAttributes[checkType] == null) continue;
- if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE &&
- noMobileData) {
- loge("not failing over to mobile type " + checkType +
- " because Mobile Data Disabled");
- continue;
- }
if (mNetAttributes[checkType].isDefault()) {
/* TODO - if we have multiple nets we could use
* we may want to put more thought into which we choose
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 069e1b8..737342f 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -30,6 +30,7 @@
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
+import android.os.Messenger;
import android.os.ServiceManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
@@ -81,6 +82,10 @@
DORMANT
}
+ public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER =
+ "com.android.internal.telephony";
+ public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
+
/***** Event Codes *****/
protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
protected static final int EVENT_RADIO_AVAILABLE = 3;
@@ -113,6 +118,8 @@
protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37;
protected static final int EVENT_RESET_DONE = 38;
+ public static final int CMD_SET_DATA_ENABLE = 39;
+
/***** Constants *****/
protected static final int APN_INVALID_ID = -1;
@@ -123,13 +130,18 @@
protected static final int APN_HIPRI_ID = 4;
protected static final int APN_NUM_TYPES = 5;
- protected static final int DISABLED = 0;
- protected static final int ENABLED = 1;
+ public static final int DISABLED = 0;
+ public static final int ENABLED = 1;
// responds to the setInternalDataEnabled call - used internally to turn off data
// for example during emergency calls
protected boolean mInternalDataEnabled = true;
+ // responds to public (user) API to enable/disable data use
+ // independent of mInternalDataEnabled and requests for APN access
+ // persisted
+ protected boolean mDataEnabled = true;
+
protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
protected int enabledCount = 0;
@@ -289,6 +301,9 @@
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(),
+ Settings.Secure.MOBILE_DATA, 1) == 1;
+
// TODO: Why is this registering the phone as the receiver of the intent
// and not its own handler?
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
@@ -296,16 +311,8 @@
// This preference tells us 1) initial condition for "dataEnabled",
// and 2) whether the RIL will setup the baseband to auto-PS attach.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
- boolean dataEnabledSetting = true;
- try {
- dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager.
- getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled();
- } catch (Exception e) {
- // nothing to do - use the old behavior and leave data on
- }
dataEnabled[APN_DEFAULT_ID] =
- !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false) &&
- dataEnabledSetting;
+ !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
if (dataEnabled[APN_DEFAULT_ID]) {
enabledCount++;
}
@@ -316,6 +323,12 @@
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
}
+ protected void broadcastMessenger() {
+ Intent intent = new Intent(ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
+ intent.putExtra(EXTRA_MESSENGER, new Messenger(this));
+ mPhone.getContext().sendBroadcast(intent);
+ }
+
public Activity getActivity() {
return mActivity;
}
@@ -490,14 +503,20 @@
onCleanUpConnection(tearDown, (String) msg.obj);
break;
- case EVENT_SET_INTERNAL_DATA_ENABLE:
+ case EVENT_SET_INTERNAL_DATA_ENABLE: {
boolean enabled = (msg.arg1 == ENABLED) ? true : false;
onSetInternalDataEnabled(enabled);
break;
-
+ }
case EVENT_RESET_DONE:
onResetDone((AsyncResult) msg.obj);
break;
+ case CMD_SET_DATA_ENABLE: {
+ log("CMD_SET_DATA_ENABLE msg=" + msg);
+ boolean enabled = (msg.arg1 == ENABLED) ? true : false;
+ onSetDataEnabled(enabled);
+ break;
+ }
default:
Log.e("DATA", "Unidentified event = " + msg.what);
@@ -512,7 +531,7 @@
* {@code true} otherwise.
*/
public synchronized boolean getAnyDataEnabled() {
- return (mInternalDataEnabled && (enabledCount != 0));
+ return (mInternalDataEnabled && mDataEnabled && (enabledCount != 0));
}
protected abstract void startNetStatPoll();
@@ -828,11 +847,6 @@
* Prevent mobile data connections from being established, or once again
* allow mobile data connections. If the state toggles, then either tear
* down or set up data, as appropriate to match the new state.
- * <p>
- * This operation only affects the default APN, and if the same APN is
- * currently being used for MMS traffic, the teardown will not happen even
- * when {@code enable} is {@code false}.
- * </p>
*
* @param enable indicates whether to enable ({@code true}) or disable (
* {@code false}) data
@@ -849,15 +863,41 @@
}
protected void onSetInternalDataEnabled(boolean enable) {
+ boolean prevEnabled = getAnyDataEnabled();
if (mInternalDataEnabled != enable) {
synchronized (this) {
mInternalDataEnabled = enable;
}
- if (enable) {
- mRetryMgr.resetRetryCount();
- onTrySetupData(Phone.REASON_DATA_ENABLED);
- } else {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ if (prevEnabled != getAnyDataEnabled()) {
+ if (!prevEnabled) {
+ mRetryMgr.resetRetryCount();
+ onTrySetupData(Phone.REASON_DATA_ENABLED);
+ } else {
+ onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ }
+ }
+ }
+ }
+
+ public synchronized boolean getDataEnabled() {
+ return mDataEnabled;
+ }
+
+ protected void onSetDataEnabled(boolean enable) {
+ boolean prevEnabled = getAnyDataEnabled();
+ if (mDataEnabled != enable) {
+ synchronized (this) {
+ mDataEnabled = enable;
+ }
+ Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
+ Settings.Secure.MOBILE_DATA, enable ? 1 : 0);
+ if (prevEnabled != getAnyDataEnabled()) {
+ if (!prevEnabled) {
+ mRetryMgr.resetRetryCount();
+ onTrySetupData(Phone.REASON_DATA_ENABLED);
+ } else {
+ onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ }
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index b005cd3..60df7df 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -113,6 +113,7 @@
mDataConnectionTracker = this;
createAllDataConnectionList();
+ broadcastMessenger();
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 4713c24..cd0d9e3 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -160,6 +160,7 @@
/** Create the default connection */
createDataConnection(Phone.APN_TYPE_DEFAULT);
+ broadcastMessenger();
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 58a4cba..461f01d 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -386,7 +386,9 @@
Connection dial(String originalNumber) throws SipException {
String calleeSipUri = originalNumber;
if (!calleeSipUri.contains("@")) {
- calleeSipUri += "@" + getSipDomain(mProfile);
+ calleeSipUri = mProfile.getUriString().replaceFirst(
+ mProfile.getUserName() + "@",
+ calleeSipUri + "@");
}
try {
SipProfile callee =
diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
new file mode 100644
index 0000000..7d41d1c
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.animation.PropertyValuesHolder
+ *
+ * Through the layoutlib_create tool, the original native methods of PropertyValuesHolder have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
+ * around to map int to instance of the delegate.
+ *
+ * The main goal of this class' methods are to provide a native way to access setters and getters
+ * on some object. In this case we want to default to using Java reflection instead so the native
+ * methods do nothing.
+ *
+ */
+/*package*/ class PropertyValuesHolder_Delegate {
+
+ /*package*/ static int nGetIntMethod(Class<?> targetClass, String methodName) {
+ // return 0 to force PropertyValuesHolder to use Java reflection.
+ return 0;
+ }
+
+ /*package*/ static int nGetFloatMethod(Class<?> targetClass, String methodName) {
+ // return 0 to force PropertyValuesHolder to use Java reflection.
+ return 0;
+ }
+
+ /*package*/ static void nCallIntMethod(Object target, int methodID, int arg) {
+ // do nothing
+ }
+
+ /*package*/ static void nCallFloatMethod(Object target, int methodID, float arg) {
+ // do nothing
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index d58cde8..0130970 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -458,16 +458,10 @@
mCanvas.setDensity(mParams.getDensity());
}
- long preDrawTime = System.currentTimeMillis();
-
mViewRoot.draw(mCanvas);
- long drawTime = System.currentTimeMillis();
-
mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
- System.out.println(String.format("rendering (ms): %03d", drawTime - preDrawTime));
-
// success!
return SceneStatus.SUCCESS.createResult();
} catch (Throwable e) {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 4440685..1d40d33 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -105,6 +105,7 @@
* The list of classes on which to delegate all native methods.
*/
private final static String[] DELEGATE_CLASS_NATIVES = new String[] {
+ "android.animation.PropertyValuesHolder",
"android.graphics.Bitmap",
"android.graphics.Canvas",
"android.graphics.DashPathEffect",
diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java
index 6977e30..4029ed0 100644
--- a/voip/java/android/net/sip/SipProfile.java
+++ b/voip/java/android/net/sip/SipProfile.java
@@ -20,6 +20,7 @@
import android.os.Parcelable;
import android.text.TextUtils;
+import java.io.ObjectStreamException;
import java.io.Serializable;
import java.text.ParseException;
import javax.sip.InvalidArgumentException;
@@ -40,12 +41,15 @@
public class SipProfile implements Parcelable, Serializable, Cloneable {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_PORT = 5060;
+ private static final String TCP = "TCP";
+ private static final String UDP = "UDP";
private Address mAddress;
private String mProxyAddress;
private String mPassword;
private String mDomain;
- private String mProtocol = ListeningPoint.UDP;
+ private String mProtocol = UDP;
private String mProfileName;
+ private int mPort = DEFAULT_PORT;
private boolean mSendKeepAlive = false;
private boolean mAutoRegistration = true;
private transient int mCallingUid = 0;
@@ -95,6 +99,7 @@
mUri.setUserPassword(profile.getPassword());
mDisplayName = profile.getDisplayName();
mProxyAddress = profile.getProxyAddress();
+ mProfile.mPort = profile.getPort();
}
/**
@@ -171,12 +176,11 @@
* @throws IllegalArgumentException if the port number is out of range
*/
public Builder setPort(int port) throws IllegalArgumentException {
- try {
- mUri.setPort(port);
- return this;
- } catch (InvalidArgumentException e) {
- throw new IllegalArgumentException(e);
+ if ((port > 65535) || (port < 1000)) {
+ throw new IllegalArgumentException("incorrect port arugment");
}
+ mProfile.mPort = port;
+ return this;
}
/**
@@ -193,7 +197,7 @@
throw new NullPointerException("protocol cannot be null");
}
protocol = protocol.toUpperCase();
- if (!protocol.equals("UDP") && !protocol.equals("TCP")) {
+ if (!protocol.equals(UDP) && !protocol.equals(TCP)) {
throw new IllegalArgumentException(
"unsupported protocol: " + protocol);
}
@@ -258,13 +262,22 @@
mProfile.mPassword = mUri.getUserPassword();
mUri.setUserPassword(null);
try {
- mProfile.mAddress = mAddressFactory.createAddress(
- mDisplayName, mUri);
if (!TextUtils.isEmpty(mProxyAddress)) {
SipURI uri = (SipURI)
mAddressFactory.createURI(fix(mProxyAddress));
mProfile.mProxyAddress = uri.getHost();
+ } else {
+ if (!mProfile.mProtocol.equals(UDP)) {
+ mUri.setTransportParam(mProfile.mProtocol);
+ }
+ if (mProfile.mPort != DEFAULT_PORT) {
+ mUri.setPort(mProfile.mPort);
+ }
}
+ mProfile.mAddress = mAddressFactory.createAddress(
+ mDisplayName, mUri);
+ } catch (InvalidArgumentException e) {
+ throw new RuntimeException(e);
} catch (ParseException e) {
// must not occur
throw new RuntimeException(e);
@@ -286,6 +299,7 @@
mSendKeepAlive = (in.readInt() == 0) ? false : true;
mAutoRegistration = (in.readInt() == 0) ? false : true;
mCallingUid = in.readInt();
+ mPort = in.readInt();
}
@Override
@@ -299,6 +313,7 @@
out.writeInt(mSendKeepAlive ? 1 : 0);
out.writeInt(mAutoRegistration ? 1 : 0);
out.writeInt(mCallingUid);
+ out.writeInt(mPort);
}
@Override
@@ -322,7 +337,13 @@
* @return the SIP URI string of this profile
*/
public String getUriString() {
- return mAddress.getURI().toString();
+ // We need to return the sip uri domain instead of
+ // the SIP URI with transport, port information if
+ // the outbound proxy address exists.
+ if (!TextUtils.isEmpty(mProxyAddress)) {
+ return "sip:" + getUserName() + "@" + mDomain;
+ }
+ return getUri().toString();
}
/**
@@ -377,8 +398,7 @@
* @return the port number of the SIP server
*/
public int getPort() {
- int port = getUri().getPort();
- return (port == -1) ? DEFAULT_PORT : port;
+ return mPort;
}
/**
@@ -441,4 +461,10 @@
public int getCallingUid() {
return mCallingUid;
}
+
+ private Object readResolve() throws ObjectStreamException {
+ // For compatibility.
+ if (mPort == 0) mPort = DEFAULT_PORT;
+ return this;
+ }
}
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 13e6f14..518543a 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -215,8 +215,9 @@
String tag) throws ParseException, SipException {
FromHeader fromHeader = createFromHeader(userProfile, tag);
ToHeader toHeader = createToHeader(userProfile);
- SipURI requestURI = mAddressFactory.createSipURI("sip:"
- + userProfile.getSipDomain());
+ SipURI requestURI = mAddressFactory.createSipURI(
+ userProfile.getUriString().replaceFirst(
+ userProfile.getUserName() + "@", ""));
List<ViaHeader> viaHeaders = createViaHeaders();
CallIdHeader callIdHeader = createCallIdHeader();
CSeqHeader cSeqHeader = createCSeqHeader(requestType);
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index d0231be..2aff7ec 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -170,6 +170,13 @@
}
/**
+ * @param enabled
+ */
+ public void setDataEnable(boolean enabled) {
+ android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
+ }
+
+ /**
* Check if private DNS route is set for the network
*/
public boolean isPrivateDnsRouteSet() {