Merge "Multiline EditText have top and bottom brackets to differentiate from single line."
diff --git a/api/current.xml b/api/current.xml
index 19c1384..357daae 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -21087,6 +21087,32 @@
<parameter name="nonRoot" type="boolean">
</parameter>
</method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
<method name="onActivityResult"
return="void"
abstract="false"
@@ -21722,19 +21748,6 @@
visibility="protected"
>
</method>
-<method name="onStartActionMode"
- return="android.view.ActionMode"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.view.ActionMode.Callback">
-</parameter>
-</method>
<method name="onStop"
return="void"
abstract="false"
@@ -21835,6 +21848,19 @@
<parameter name="hasFocus" type="boolean">
</parameter>
</method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
<method name="openContextMenu"
return="void"
abstract="false"
@@ -21885,47 +21911,6 @@
<parameter name="exitAnim" type="int">
</parameter>
</method>
-<method name="popBackStack"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-</method>
-<method name="popBackStack"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<method name="popBackStack"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-<parameter name="id" type="int">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
<method name="registerForContextMenu"
return="void"
abstract="false"
@@ -22611,17 +22596,6 @@
visibility="protected"
>
</field>
-<field name="POP_BACK_STACK_INCLUSIVE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="RESULT_CANCELED"
type="int"
transient="false"
@@ -25434,6 +25408,32 @@
visibility="public"
>
</method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
<method name="onAttachedToWindow"
return="void"
abstract="false"
@@ -25784,19 +25784,6 @@
visibility="protected"
>
</method>
-<method name="onStartActionMode"
- return="android.view.ActionMode"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.view.ActionMode.Callback">
-</parameter>
-</method>
<method name="onStop"
return="void"
abstract="false"
@@ -25860,6 +25847,19 @@
<parameter name="hasFocus" type="boolean">
</parameter>
</method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
<method name="openContextMenu"
return="void"
abstract="false"
@@ -28308,6 +28308,17 @@
<parameter name="args" type="java.lang.String[]">
</parameter>
</method>
+<method name="executePendingTransactions"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="findFragmentById"
return="android.app.Fragment"
abstract="true"
@@ -28374,7 +28385,7 @@
>
</method>
<method name="popBackStack"
- return="boolean"
+ return="void"
abstract="true"
native="false"
synchronized="false"
@@ -28385,7 +28396,7 @@
>
</method>
<method name="popBackStack"
- return="boolean"
+ return="void"
abstract="true"
native="false"
synchronized="false"
@@ -28400,6 +28411,47 @@
</parameter>
</method>
<method name="popBackStack"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="popBackStackImmediate"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="popBackStackImmediate"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="popBackStackImmediate"
return="boolean"
abstract="true"
native="false"
@@ -212083,6 +212135,32 @@
<parameter name="event" type="android.view.MotionEvent">
</parameter>
</method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
<method name="onAttachedToWindow"
return="void"
abstract="true"
@@ -212217,19 +212295,6 @@
visibility="public"
>
</method>
-<method name="onStartActionMode"
- return="android.view.ActionMode"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.view.ActionMode.Callback">
-</parameter>
-</method>
<method name="onWindowAttributesChanged"
return="void"
abstract="true"
@@ -212256,6 +212321,19 @@
<parameter name="hasFocus" type="boolean">
</parameter>
</method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
</interface>
<interface name="WindowManager"
abstract="true"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 33f88d8..5174f19 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2086,63 +2086,12 @@
}
/**
- * Flag for {@link #popBackStack(String, int)}
- * and {@link #popBackStack(int, int)}: If set, and the name or ID of
- * a back stack entry has been supplied, then all matching entries will
- * be consumed until one that doesn't match is found or the bottom of
- * the stack is reached. Otherwise, all entries up to but not including that entry
- * will be removed.
- */
- public static final int POP_BACK_STACK_INCLUSIVE = 1<<0;
-
- /**
- * Pop the top state off the back stack. Returns true if there was one
- * to pop, else false.
- * @deprecated use {@link #getFragmentManager}.
- */
- @Deprecated
- public boolean popBackStack() {
- return mFragments.popBackStack();
- }
-
- /**
- * Pop the last fragment transition from the local activity's fragment
- * back stack. If there is nothing to pop, false is returned.
- * @param name If non-null, this is the name of a previous back state
- * to look for; if found, all states up to that state will be popped. The
- * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
- * the named state itself is popped. If null, only the top state is popped.
- * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
- * @deprecated use {@link #getFragmentManager}.
- */
- @Deprecated
- public boolean popBackStack(String name, int flags) {
- return mFragments.popBackStack(name, flags);
- }
-
- /**
- * Pop all back stack states up to the one with the given identifier.
- * @param id Identifier of the stated to be popped. If no identifier exists,
- * false is returned.
- * The identifier is the number returned by
- * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. The
- * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
- * the named state itself is popped.
- * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
- * @deprecated use {@link #getFragmentManager}.
- */
- @Deprecated
- public boolean popBackStack(int id, int flags) {
- return mFragments.popBackStack(id, flags);
- }
-
- /**
* Called when the activity has detected the user's press of the back
* key. The default implementation simply finishes the current activity,
* but you can override this to do whatever you want.
*/
public void onBackPressed() {
- if (!mFragments.popBackStack()) {
+ if (!mFragments.popBackStackImmediate()) {
finish();
}
}
@@ -4174,7 +4123,7 @@
}
/**
- * Start a context mode.
+ * Start an action mode.
*
* @param callback Callback that will manage lifecycle events for this context mode
* @return The ContextMode that was started, or null if it was canceled
@@ -4185,7 +4134,18 @@
return mWindow.getDecorView().startActionMode(callback);
}
- public ActionMode onStartActionMode(ActionMode.Callback callback) {
+ /**
+ * Give the Activity a chance to control the UI for an action mode requested
+ * by the system.
+ *
+ * <p>Note: If you are looking for a notification callback that an action mode
+ * has been started for this activity, see {@link #onActionModeStarted(ActionMode)}.</p>
+ *
+ * @param callback The callback that should control the new action mode
+ * @return The new action mode, or <code>null</code> if the activity does not want to
+ * provide special handling for this action mode. (It will be handled by the system.)
+ */
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
initActionBar();
if (mActionBar != null) {
return mActionBar.startActionMode(callback);
@@ -4193,6 +4153,24 @@
return null;
}
+ /**
+ * Notifies the Activity that an action mode has been started.
+ * Activity subclasses overriding this method should call the superclass implementation.
+ *
+ * @param mode The new action mode.
+ */
+ public void onActionModeStarted(ActionMode mode) {
+ }
+
+ /**
+ * Notifies the activity that an action mode has finished.
+ * Activity subclasses overriding this method should call the superclass implementation.
+ *
+ * @param mode The action mode that just finished.
+ */
+ public void onActionModeFinished(ActionMode mode) {
+ }
+
// ------------------ Internal API ------------------
final void setParent(Activity parent) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 526129a..64a4d7a 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -867,13 +867,19 @@
}
}
- public ActionMode onStartActionMode(ActionMode.Callback callback) {
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
if (mActionBar != null) {
return mActionBar.startActionMode(callback);
}
return null;
}
+ public void onActionModeStarted(ActionMode mode) {
+ }
+
+ public void onActionModeFinished(ActionMode mode) {
+ }
+
/**
* @return The activity associated with this dialog, or null if there is no associated activity.
*/
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 9970418..d3a4f33 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,6 +22,7 @@
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
@@ -99,6 +100,20 @@
public abstract FragmentTransaction openTransaction();
/**
+ * After a {@link FragmentTransaction} is committed with
+ * {@link FragmentTransaction#commit FragmentTransaction.commit()}, it
+ * is scheduled to be executed asynchronously on the process's main thread.
+ * If you want to immediately executing any such pending operations, you
+ * can call this function (only from the main thread) to do so. Note that
+ * all callbacks and other related behavior will be done from within this
+ * call, so be careful about where this is called from.
+ *
+ * @return Returns true if there were any pending transactions to be
+ * executed.
+ */
+ public abstract boolean executePendingTransactions();
+
+ /**
* Finds a fragment that was identified by the given id either when inflated
* from XML or as the container ID when added in a transaction. This first
* searches through fragments that are currently added to the manager's
@@ -132,7 +147,15 @@
* Pop the top state off the back stack. Returns true if there was one
* to pop, else false.
*/
- public abstract boolean popBackStack();
+ public abstract void popBackStack();
+
+ /**
+ * Like {@link #popBackStack()}, but performs the operation immediately
+ * inside of the call. This is like calling {@link #executePendingTransactions()}
+ * afterwards.
+ * @return Returns true if there was something popped, else false.
+ */
+ public abstract boolean popBackStackImmediate();
/**
* Pop the last fragment transition from the manager's fragment
@@ -143,7 +166,15 @@
* the named state itself is popped. If null, only the top state is popped.
* @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
*/
- public abstract boolean popBackStack(String name, int flags);
+ public abstract void popBackStack(String name, int flags);
+
+ /**
+ * Like {@link #popBackStack(String, int)}, but performs the operation immediately
+ * inside of the call. This is like calling {@link #executePendingTransactions()}
+ * afterwards.
+ * @return Returns true if there was something popped, else false.
+ */
+ public abstract boolean popBackStackImmediate(String name, int flags);
/**
* Pop all back stack states up to the one with the given identifier.
@@ -155,7 +186,15 @@
* the named state itself is popped.
* @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
*/
- public abstract boolean popBackStack(int id, int flags);
+ public abstract void popBackStack(int id, int flags);
+
+ /**
+ * Like {@link #popBackStack(int, int)}, but performs the operation immediately
+ * inside of the call. This is like calling {@link #executePendingTransactions()}
+ * afterwards.
+ * @return Returns true if there was something popped, else false.
+ */
+ public abstract boolean popBackStackImmediate(int id, int flags);
/**
* Return the number of entries currently in the back stack.
@@ -300,17 +339,58 @@
}
@Override
- public boolean popBackStack() {
+ public boolean executePendingTransactions() {
+ return execPendingActions();
+ }
+
+ @Override
+ public void popBackStack() {
+ enqueueAction(new Runnable() {
+ @Override public void run() {
+ popBackStackState(mActivity.mHandler, null, -1, 0);
+ }
+ }, false);
+ }
+
+ @Override
+ public boolean popBackStackImmediate() {
+ checkStateLoss();
+ executePendingTransactions();
return popBackStackState(mActivity.mHandler, null, -1, 0);
}
@Override
- public boolean popBackStack(String name, int flags) {
+ public void popBackStack(final String name, final int flags) {
+ enqueueAction(new Runnable() {
+ @Override public void run() {
+ popBackStackState(mActivity.mHandler, name, -1, flags);
+ }
+ }, false);
+ }
+
+ @Override
+ public boolean popBackStackImmediate(String name, int flags) {
+ checkStateLoss();
+ executePendingTransactions();
return popBackStackState(mActivity.mHandler, name, -1, flags);
}
@Override
- public boolean popBackStack(int id, int flags) {
+ public void popBackStack(final int id, final int flags) {
+ if (id < 0) {
+ throw new IllegalArgumentException("Bad id: " + id);
+ }
+ enqueueAction(new Runnable() {
+ @Override public void run() {
+ popBackStackState(mActivity.mHandler, null, id, flags);
+ }
+ }, false);
+ }
+
+ @Override
+ public boolean popBackStackImmediate(int id, int flags) {
+ checkStateLoss();
+ executePendingTransactions();
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
}
@@ -849,16 +929,20 @@
return null;
}
+ private void checkStateLoss() {
+ if (mStateSaved) {
+ throw new IllegalStateException(
+ "Can not perform this action after onSaveInstanceState");
+ }
+ if (mNoTransactionsBecause != null) {
+ throw new IllegalStateException(
+ "Can not perform this action inside of " + mNoTransactionsBecause);
+ }
+ }
+
public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
- if (mStateSaved) {
- throw new IllegalStateException(
- "Can not perform this action after onSaveInstanceState");
- }
- if (mNoTransactionsBecause != null) {
- throw new IllegalStateException(
- "Can not perform this action inside of " + mNoTransactionsBecause);
- }
+ checkStateLoss();
}
synchronized (this) {
if (mActivity == null) {
@@ -934,17 +1018,23 @@
/**
* Only call from main thread!
*/
- public void execPendingActions() {
+ public boolean execPendingActions() {
if (mExecutingActions) {
- throw new IllegalStateException("Recursive entry to execPendingActions");
+ throw new IllegalStateException("Recursive entry to executePendingTransactions");
}
+ if (Looper.myLooper() != Looper.getMainLooper()) {
+ throw new IllegalStateException("Must be called from main thread of process");
+ }
+
+ boolean didSomething = false;
+
while (true) {
int numActions;
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
- return;
+ return didSomething;
}
numActions = mPendingActions.size();
@@ -961,6 +1051,7 @@
mTmpActions[i].run();
}
mExecutingActions = false;
+ didSomething = true;
}
}
@@ -984,19 +1075,14 @@
if (mBackStack == null) {
return false;
}
- if (name == null && id < 0 && (flags&Activity.POP_BACK_STACK_INCLUSIVE) == 0) {
+ if (name == null && id < 0 && (flags&POP_BACK_STACK_INCLUSIVE) == 0) {
int last = mBackStack.size()-1;
if (last < 0) {
return false;
}
final BackStackRecord bss = mBackStack.remove(last);
- enqueueAction(new Runnable() {
- public void run() {
- if (DEBUG) Log.v(TAG, "Popping back stack state: " + bss);
- bss.popFromBackStack(true);
- reportBackStackChanged();
- }
- }, false);
+ bss.popFromBackStack(true);
+ reportBackStackChanged();
} else {
int index = -1;
if (name != null || id >= 0) {
@@ -1016,7 +1102,7 @@
if (index < 0) {
return false;
}
- if ((flags&Activity.POP_BACK_STACK_INCLUSIVE) != 0) {
+ if ((flags&POP_BACK_STACK_INCLUSIVE) != 0) {
index--;
// Consume all following entries that match.
while (index >= 0) {
@@ -1038,16 +1124,12 @@
for (int i=mBackStack.size()-1; i>index; i--) {
states.add(mBackStack.remove(i));
}
- enqueueAction(new Runnable() {
- public void run() {
- final int LAST = states.size()-1;
- for (int i=0; i<=LAST; i++) {
- if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
- states.get(i).popFromBackStack(i == LAST);
- }
- reportBackStackChanged();
- }
- }, false);
+ final int LAST = states.size()-1;
+ for (int i=0; i<=LAST; i++) {
+ if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
+ states.get(i).popFromBackStack(i == LAST);
+ }
+ reportBackStackChanged();
}
return true;
}
@@ -1084,6 +1166,10 @@
}
Parcelable saveAllState() {
+ // Make sure all pending operations have now been executed to get
+ // our state update-to-date.
+ execPendingActions();
+
mStateSaved = true;
if (mActive == null || mActive.size() <= 0) {
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index a47c66a..47a7696 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -169,7 +169,12 @@
is = getInputStream();
if (is == null) return null;
byte[] buf = new byte[maxBytes];
- return new String(buf, 0, Math.max(0, is.read(buf)));
+ int readBytes = 0;
+ int n = 0;
+ while (n >= 0 && (readBytes += n) < maxBytes) {
+ n = is.read(buf, readBytes, maxBytes - readBytes);
+ }
+ return new String(buf, 0, readBytes);
} catch (IOException e) {
return null;
} finally {
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 8762512..97f015b 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -106,6 +106,8 @@
private static final String TAG = "StrictMode";
private static final boolean LOG_V = false;
+ private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
+
// Only log a duplicate stack trace to the logs every second.
private static final long MIN_LOG_INTERVAL_MS = 1000;
@@ -693,7 +695,7 @@
public static boolean conditionallyEnableDebugLogging() {
// For debug builds, log event loop stalls to dropbox for analysis.
// Similar logic also appears in ActivityThread.java for system apps.
- if ("user".equals(Build.TYPE)) {
+ if (IS_USER_BUILD) {
setCloseGuardEnabled(false);
return false;
}
@@ -1240,6 +1242,11 @@
mContainerState = threadState;
}
+ // Empty constructor for the NO_OP_SPAN
+ protected Span() {
+ mContainerState = null;
+ }
+
/**
* To be called when the critical span is complete (i.e. the
* animation is done animating). This can be called on any
@@ -1286,6 +1293,13 @@
}
}
+ // The no-op span that's used in user builds.
+ private static final Span NO_OP_SPAN = new Span() {
+ public void finish() {
+ // Do nothing.
+ }
+ };
+
/**
* Linked lists of active spans and a freelist.
*
@@ -1327,6 +1341,9 @@
* @hide
*/
public static Span enterCriticalSpan(String name) {
+ if (IS_USER_BUILD) {
+ return NO_OP_SPAN;
+ }
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("name must be non-null and non-empty");
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 0ce69ad..39f3cee 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -23,6 +23,7 @@
import android.app.Fragment;
import android.app.FragmentBreadCrumbs;
+import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListActivity;
import android.content.Context;
@@ -902,7 +903,8 @@
}
private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
- getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
+ getFragmentManager().popBackStack(BACK_STACK_PREFS,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
Fragment f = Fragment.instantiate(this, fragmentName, args);
FragmentTransaction transaction = getFragmentManager().openTransaction();
transaction.setTransition(direction == 0 ? FragmentTransaction.TRANSIT_NONE
@@ -934,7 +936,8 @@
if (mCurHeader == header) {
// This is the header we are currently displaying. Just make sure
// to pop the stack up to its root state.
- getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
+ getFragmentManager().popBackStack(BACK_STACK_PREFS,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
@@ -1061,14 +1064,14 @@
setResult(resultCode, resultData);
finish();
} else {
+ // XXX be smarter about popping the stack.
+ onBackPressed();
if (caller != null) {
if (caller.getTargetFragment() != null) {
caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(),
resultCode, resultData);
}
}
- // XXX be smarter about popping the stack.
- onBackPressed();
}
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index d5d9a2e..5385cd9 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -313,12 +313,31 @@
public boolean onSearchRequested();
/**
- * Called when an action mode is being started.
+ * Called when an action mode is being started for this window. Gives the
+ * callback an opportunity to handle the action mode in its own unique and
+ * beautiful way. If this method returns null the system can choose a way
+ * to present the mode or choose not to start the mode at all.
*
* @param callback Callback to control the lifecycle of this action mode
- * @return The ActionMode that was started, or null if it was canceled
+ * @return The ActionMode that was started, or null if the system should present it
*/
- public ActionMode onStartActionMode(ActionMode.Callback callback);
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback);
+
+ /**
+ * Called when an action mode has been started. The appropriate mode callback
+ * method will have already been invoked.
+ *
+ * @param mode The new mode that has just been started.
+ */
+ public void onActionModeStarted(ActionMode mode);
+
+ /**
+ * Called when an action mode has been finished. The appropriate mode callback
+ * method will have already been invoked.
+ *
+ * @param mode The mode that was just finished.
+ */
+ public void onActionModeFinished(ActionMode mode);
}
public Window(Context context) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 14dbfe2..06800d5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2384,7 +2384,6 @@
Rect sendOurVisibleRect() {
if (mZoomManager.isPreventingWebkitUpdates()) return mLastVisibleRectSent;
-
Rect rect = new Rect();
calcOurContentVisibleRect(rect);
// Rect.equals() checks for null input.
@@ -2937,7 +2936,8 @@
postInvalidate(); // So we draw again
if (oldX != mScrollX || oldY != mScrollY) {
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
- } else {
+ } else if (mScroller.getStartX() != mScrollX
+ || mScroller.getStartY() != mScrollY) {
abortAnimation();
mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
WebViewCore.resumePriority();
@@ -2970,6 +2970,7 @@
if ((dx | dy) == 0) {
return false;
}
+ abortAnimation();
if (animate) {
// Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
mScroller.startScroll(mScrollX, mScrollY, dx, dy,
@@ -2977,7 +2978,6 @@
awakenScrollBars(mScroller.getDuration());
invalidate();
} else {
- abortAnimation(); // just in case
scrollTo(x, y);
}
return true;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ab5ff3d..30b1e5d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2893,8 +2893,8 @@
void reportScrollStateChange(int newState) {
if (newState != mLastScrollState) {
if (mOnScrollListener != null) {
- mOnScrollListener.onScrollStateChanged(this, newState);
mLastScrollState = newState;
+ mOnScrollListener.onScrollStateChanged(this, newState);
}
}
}
@@ -3431,12 +3431,13 @@
public void smoothScrollBy(int distance, int duration) {
if (mFlingRunnable == null) {
mFlingRunnable = new FlingRunnable();
- } else {
- mFlingRunnable.endFling();
}
// No sense starting to scroll if we're not going anywhere
if (distance != 0) {
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
mFlingRunnable.startScroll(distance, duration);
+ } else {
+ mFlingRunnable.endFling();
}
}
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 1d103ed..1406e4e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -110,8 +110,10 @@
if (isShowing()) {
mPopup.dismiss();
}
- mTreeObserver.removeGlobalOnLayoutListener(this);
- mTreeObserver = null;
+ if (mTreeObserver != null) {
+ mTreeObserver.removeGlobalOnLayoutListener(this);
+ mTreeObserver = null;
+ }
}
public boolean isShowing() {
diff --git a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
new file mode 100755
index 0000000..2b0e4af
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <accesspoint>
+ <ssid>opennet</ssid>
+ <security>NONE</security>
+ </accesspoint>
+ <accesspoint>
+ <ssid>GoogleGuest</ssid>
+ <security>NONE</security>
+ </accesspoint>
+ <accesspoint>
+ <ssid>securenetdhcp</ssid>
+ <security>PSK</security>
+ <password>androidwifi</password>
+ </accesspoint>
+ <accesspoint>
+ <ssid>botnet</ssid>
+ <security>EAP</security>
+ <eap>PEAP</eap>
+ <phase2>MSCHAPV2</phase2>
+ <identity>donut</identity>
+ <password>android</password>
+ </accesspoint>
+</resources>
+
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
new file mode 100644
index 0000000..863fbe6
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -0,0 +1,262 @@
+/*
+ * 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;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+
+import android.util.Log;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Help class to process configurations of access points saved in an XML file.
+ * The configurations of an access point is included in tag
+ * <accesspoint></accesspoint>. The supported configuration includes: ssid,
+ * security, eap, phase2, identity, password, anonymousidentity, cacert, usercert,
+ * in which each is included in the corresponding tags. All access points have to be
+ * enclosed in tags of <resources></resources>.
+ *
+ * The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2.
+ * <resources>
+ * <accesspoint>
+ * <ssid>testnet</ssid>
+ * <security>EAP</security>
+ * <eap>PEAP</eap>
+ * <phase2>MSCHAP2</phase2>
+ * <identity>donut</identity</identity>
+ * <password>abcdefgh</password>
+ * </accesspoint>
+ * </resources>
+ */
+public class AccessPointParserHelper {
+ private static final String KEYSTORE_SPACE = "keystore://";
+ private static final String TAG = "AccessPointParserHelper";
+ static final int NONE = 0;
+ static final int WEP = 1;
+ static final int PSK = 2;
+ static final int EAP = 3;
+
+ List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
+
+ private int getSecurityType (String security) {
+ if (security.equalsIgnoreCase("NONE")) {
+ return NONE;
+ } else if (security.equalsIgnoreCase("WEP")) {
+ return WEP;
+ } else if (security.equalsIgnoreCase("PSK")) {
+ return PSK;
+ } else if (security.equalsIgnoreCase("EAP")) {
+ return EAP;
+ } else {
+ return -1;
+ }
+ }
+
+ private boolean validateEapValue(String value) {
+ if (value.equalsIgnoreCase("PEAP") ||
+ value.equalsIgnoreCase("TLS") ||
+ value.equalsIgnoreCase("TTLS")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ DefaultHandler mHandler = new DefaultHandler() {
+
+ boolean ssid = false;
+ boolean security = false;
+ boolean password = false;
+ boolean ip = false;
+ boolean subnetmask = false;
+ boolean gateway = false;
+ boolean dns = false;
+ boolean eap = false;
+ boolean phase2 = false;
+ boolean identity = false;
+ boolean anonymousidentity = false;
+ boolean cacert = false;
+ boolean usercert = false;
+ WifiConfiguration config = null;
+ int securityType = NONE;
+
+ @Override
+ public void startElement(String uri, String localName, String tagName,
+ Attributes attributes) throws SAXException {
+ if (tagName.equalsIgnoreCase("accesspoint")) {
+ config = new WifiConfiguration();
+ }
+ if (tagName.equalsIgnoreCase("ssid")) {
+ ssid = true;
+ }
+ if (tagName.equalsIgnoreCase("security")) {
+ security = true;
+ }
+ if (tagName.equalsIgnoreCase("password")) {
+ password = true;
+ }
+ if (tagName.equalsIgnoreCase("eap")) {
+ eap = true;
+ }
+ if (tagName.equalsIgnoreCase("phase2")) {
+ phase2 = true;
+ }
+ if (tagName.equalsIgnoreCase("identity")) {
+ identity = true;
+ }
+ if (tagName.equalsIgnoreCase("anonymousidentity")) {
+ anonymousidentity = true;
+ }
+ if (tagName.equalsIgnoreCase("cacert")) {
+ cacert = true;
+ }
+ if (tagName.equalsIgnoreCase("usercert")) {
+ usercert = true;
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String tagName) throws SAXException {
+ Log.v(TAG, "endElement: " + tagName);
+ if (tagName.equalsIgnoreCase("accesspoint")) {
+ networks.add(config);
+ }
+ }
+
+ @Override
+ public void characters(char ch[], int start, int length) throws SAXException {
+ if (ssid) {
+ config.SSID = new String(ch, start, length);
+ Log.v(TAG, "ssid: " + config.SSID);
+ ssid = false;
+ }
+ if (security) {
+ String securityStr = (new String(ch, start, length)).toUpperCase();
+ Log.v(TAG, "security: " + securityStr);
+ securityType = getSecurityType(securityStr);
+ Log.v(TAG, "securityType = " + securityType);
+ switch (securityType) {
+ case NONE:
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ break;
+ case WEP:
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+ config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+ break;
+ case PSK:
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ break;
+ case EAP:
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ break;
+ default:
+ throw new SAXException();
+ }
+ security = false;
+ }
+ if (password) {
+ String passwordStr = new String(ch, start, length);
+ int len = passwordStr.length();
+ if (len == 0) {
+ throw new SAXException();
+ }
+ Log.v(TAG, "passwordStr:" + passwordStr);
+ if (securityType == WEP) {
+ if ((len == 10 || len == 26 || len == 58) &&
+ passwordStr.matches("[0-9A-Fa-f]*")) {
+ config.wepKeys[0] = passwordStr;
+ } else {
+ config.wepKeys[0] = '"' + passwordStr + '"';
+ }
+ } else if (securityType == PSK) {
+ if (passwordStr.matches("[0-9A-Fa-f]{64}")) {
+ config.preSharedKey = passwordStr;
+ } else {
+ config.preSharedKey = '"' + passwordStr + '"';
+ }
+ } else if (securityType == EAP) {
+ config.password.setValue(passwordStr);
+ } else {
+ throw new SAXException();
+ }
+ password = false;
+ }
+ if (eap) {
+ String eapValue = new String(ch, start, length);
+ if (!validateEapValue(eapValue)) {
+ throw new SAXException();
+ }
+ config.eap.setValue(eapValue);
+ eap = false;
+ }
+ if (phase2) {
+ String phase2Value = new String(ch, start, length);
+ config.phase2.setValue("auth=" + phase2Value);
+ phase2 = false;
+ }
+ if (identity) {
+ String identityValue = new String(ch, start, length);
+ config.identity.setValue(identityValue);
+ identity = false;
+ }
+ if (anonymousidentity) {
+ String anonyId = new String(ch, start, length);
+ config.anonymous_identity.setValue(anonyId);
+ anonymousidentity = false;
+ }
+ if (cacert) {
+ String cacertValue = new String(ch, start, length);
+ // need to install the credentail to "keystore://"
+ config.ca_cert.setValue(KEYSTORE_SPACE);
+ cacert = false;
+ }
+ if (usercert) {
+ String usercertValue = new String(ch, start, length);
+ config.client_cert.setValue(KEYSTORE_SPACE);
+ usercert = false;
+ }
+ }
+ };
+
+ public AccessPointParserHelper() {
+ }
+
+ /**
+ * Process the accesspoint.xml file
+ * @return List of WifiConfiguration
+ * @throws Exception when parsing the XML file
+ */
+ public List<WifiConfiguration> processAccessPoint(InputStream in) throws Exception {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser saxParser = factory.newSAXParser();
+ saxParser.parse(in, mHandler);
+ return networks;
+ }
+}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index e42b657..7c46e7a 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -16,8 +16,10 @@
package com.android.connectivitymanagertest;
+import com.android.connectivitymanagertest.R;
import android.app.Activity;
import android.content.Context;
+import android.content.res.Resources;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
@@ -25,19 +27,22 @@
import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
+
+import java.io.InputStream;
+import java.util.ArrayList;
import java.util.List;
import android.widget.LinearLayout;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
+import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration.KeyMgmt;
-
/**
* An activity registered with connectivity manager broadcast
* provides network connectivity information and
@@ -46,8 +51,11 @@
public class ConnectivityManagerTestActivity extends Activity {
public static final String LOG_TAG = "ConnectivityManagerTestActivity";
- public static final int WAIT_FOR_SCAN_RESULT = 5 * 1000; //5 seconds
+ public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
public static final int WIFI_SCAN_TIMEOUT = 20 * 1000;
+ public static final int SHORT_TIMEOUT = 5 * 1000;
+ public static final long LONG_TIMEOUT = 50 * 1000;
+ private static final String ACCESS_POINT_FILE = "accesspoints.xml";
public ConnectivityReceiver mConnectivityReceiver = null;
public WifiReceiver mWifiReceiver = null;
/*
@@ -175,6 +183,7 @@
mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(mWifiReceiver, mIntentFilter);
// Get an instance of ConnectivityManager
@@ -185,10 +194,26 @@
if (mWifiManager.isWifiEnabled()) {
Log.v(LOG_TAG, "Clear Wifi before we start the test.");
- clearWifi();
+ removeConfiguredNetworksAndDisableWifi();
}
}
+ public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
+ InputStream in = getAssets().open(ACCESS_POINT_FILE);
+ AccessPointParserHelper parseHelper = new AccessPointParserHelper();
+ return parseHelper.processAccessPoint(in);
+ }
+
+ private void printNetConfig(String[] configuration) {
+ for (int i = 0; i < configuration.length; i++) {
+ if (i == 0) {
+ Log.v(LOG_TAG, "SSID: " + configuration[0]);
+ } else {
+ Log.v(LOG_TAG, " " + configuration[i]);
+ }
+ }
+ }
+
// for each network type, initialize network states to UNKNOWN, and no verification flag is set
public void initializeNetworkStates() {
for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
@@ -245,6 +270,68 @@
}
}
+ // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED,
+ // DISCONNECTING, DISCONNECTED, UNKNOWN
+ public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ if ((System.currentTimeMillis() - startTime) > timeout) {
+ if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
+ return false;
+ } else {
+ // the broadcast has been sent out. the state has been changed.
+ Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
+ mCM.getNetworkInfo(networkType));
+ return true;
+ }
+ }
+ Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
+ " to be " + expectedState.toString());
+ synchronized (connectivityObject) {
+ try {
+ connectivityObject.wait(SHORT_TIMEOUT);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if ((mNetworkInfo.getType() != networkType) ||
+ (mNetworkInfo.getState() != expectedState)) {
+ Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
+ "is: " + mNetworkInfo.getState());
+ continue;
+ }
+ return true;
+ }
+ }
+ }
+
+ // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
+ // WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
+ public boolean waitForWifiState(int expectedState, long timeout) {
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ if ((System.currentTimeMillis() - startTime) > timeout) {
+ if (mWifiState != expectedState) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
+ synchronized (wifiObject) {
+ try {
+ wifiObject.wait(SHORT_TIMEOUT);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (mWifiState != expectedState) {
+ Log.v(LOG_TAG, "Wifi state is: " + mWifiNetworkInfo.getState());
+ continue;
+ }
+ return true;
+ }
+ }
+ }
+
// Return true if device is currently connected to mobile network
public boolean isConnectedToMobile() {
return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
@@ -265,6 +352,22 @@
* We don't verify whether the connection is successful or not, leave this to the test
*/
public boolean connectToWifi(String knownSSID) {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = knownSSID;
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ return connectToWifiWithConfiguration(config);
+ }
+
+ /**
+ * Connect to Wi-Fi with the given configuration. Note the SSID in the configuration
+ * is pure string, we need to convert it to quoted string.
+ * @param config
+ * @return
+ */
+ public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
+ String ssid = config.SSID;
+ config.SSID = convertToQuotedString(ssid);
+
//If Wifi is not enabled, enable it
if (!mWifiManager.isWifiEnabled()) {
Log.v(LOG_TAG, "Wifi is not enabled, enable it");
@@ -273,6 +376,7 @@
List<ScanResult> netList = mWifiManager.getScanResults();
if (netList == null) {
+ Log.v(LOG_TAG, "scan results are null");
// if no scan results are available, start active scan
mWifiManager.startScanActive();
mScanResultIsAvailable = false;
@@ -299,17 +403,20 @@
}
netList = mWifiManager.getScanResults();
+
for (int i = 0; i < netList.size(); i++) {
ScanResult sr= netList.get(i);
- if (sr.SSID.equals(knownSSID)) {
- Log.v(LOG_TAG, "found " + knownSSID + " in the scan result list");
- WifiConfiguration config = new WifiConfiguration();
- config.SSID = convertToQuotedString(sr.SSID);
- config.allowedKeyManagement.set(KeyMgmt.NONE);
+ if (sr.SSID.equals(ssid)) {
+ Log.v(LOG_TAG, "found " + ssid + " in the scan result list");
int networkId = mWifiManager.addNetwork(config);
// Connect to network by disabling others.
mWifiManager.enableNetwork(networkId, true);
mWifiManager.saveConfiguration();
+ List<WifiConfiguration> wifiNetworks = mWifiManager.getConfiguredNetworks();
+ for (WifiConfiguration netConfig : wifiNetworks) {
+ Log.v(LOG_TAG, netConfig.toString());
+ }
+
mWifiManager.reconnect();
break;
}
@@ -317,14 +424,14 @@
List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
if (netConfList.size() <= 0) {
- Log.v(LOG_TAG, knownSSID + " is not available");
+ Log.v(LOG_TAG, ssid + " is not available");
return false;
}
return true;
}
/*
- * Disconnect from the current AP
+ * Disconnect from the current AP and remove configured networks.
*/
public boolean disconnectAP() {
if (mWifiManager.isWifiEnabled()) {
@@ -360,9 +467,9 @@
}
/**
- * Disconnect from the current Wifi and clear the configuration list
+ * Remove configured networks and disable wifi
*/
- public boolean clearWifi() {
+ public boolean removeConfiguredNetworksAndDisableWifi() {
if (!disconnectAP()) {
return false;
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
index 592be92..3d4dc3d 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
@@ -21,6 +21,7 @@
import android.test.InstrumentationTestSuite;
import android.util.Log;
import com.android.connectivitymanagertest.functional.ConnectivityManagerMobileTest;
+import com.android.connectivitymanagertest.functional.WifiConnectionTest;
import junit.framework.TestSuite;
@@ -38,6 +39,7 @@
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
suite.addTestSuite(ConnectivityManagerMobileTest.class);
+ suite.addTestSuite(WifiConnectionTest.class);
return suite;
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index ad8d444..5959cf3 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -41,8 +41,6 @@
extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
private static final String LOG_TAG = "ConnectivityManagerMobileTest";
private static final String PKG_NAME = "com.android.connectivitymanagertest";
- private static final long STATE_TRANSITION_SHORT_TIMEOUT = 5 * 1000;
- private static final long STATE_TRANSITION_LONG_TIMEOUT = 30 * 1000;
private String TEST_ACCESS_POINT;
private ConnectivityManagerTestActivity cmActivity;
@@ -64,9 +62,14 @@
wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "CMWakeLock");
wl.acquire();
// Each test case will start with cellular connection
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
- verifyCellularConnection();
+ if (!cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT)) {
+ // Note: When the test fails in setUp(), tearDown is not called. In that case,
+ // the activity is destroyed which blocks the next test at "getActivity()".
+ // tearDown() is called hear to avoid that situation.
+ tearDown();
+ fail("Device is not connected to Mobile, setUp failed");
+ }
}
@Override
@@ -74,86 +77,26 @@
cmActivity.finish();
Log.v(LOG_TAG, "tear down ConnectivityManagerTestActivity");
wl.release();
- cmActivity.clearWifi();
+ cmActivity.removeConfiguredNetworksAndDisableWifi();
super.tearDown();
}
// help function to verify 3G connection
public void verifyCellularConnection() {
- NetworkInfo extraNetInfo = cmActivity.mNetworkInfo;
+ NetworkInfo extraNetInfo = cmActivity.mCM.getActiveNetworkInfo();
assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
- extraNetInfo.getType());
+ extraNetInfo.getType());
assertTrue("not connected to cellular network", extraNetInfo.isConnected());
assertTrue("no data connection", cmActivity.mState.equals(State.CONNECTED));
}
- // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED,
- // DISCONNECTING, DISCONNECTED, UNKNOWN
- private void waitForNetworkState(int networkType, State expectedState, long timeout) {
- long startTime = System.currentTimeMillis();
- while (true) {
- if ((System.currentTimeMillis() - startTime) > timeout) {
- if (cmActivity.mCM.getNetworkInfo(networkType).getState() != expectedState) {
- assertFalse("Wait for network state timeout", true);
- } else {
- // the broadcast has been sent out. the state has been changed.
- return;
- }
- }
- Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
- " to be " + expectedState.toString());
- synchronized (cmActivity.connectivityObject) {
- try {
- cmActivity.connectivityObject.wait(STATE_TRANSITION_SHORT_TIMEOUT);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if ((cmActivity.mNetworkInfo.getType() != networkType) ||
- (cmActivity.mNetworkInfo.getState() != expectedState)) {
- Log.v(LOG_TAG, "network state for " + cmActivity.mNetworkInfo.getType() +
- "is: " + cmActivity.mNetworkInfo.getState());
- continue;
- }
- break;
- }
- }
- }
-
- // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
- // WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
- private void waitForWifiState(int expectedState, long timeout) {
- long startTime = System.currentTimeMillis();
- while (true) {
- if ((System.currentTimeMillis() - startTime) > timeout) {
- if (cmActivity.mWifiState != expectedState) {
- assertFalse("Wait for Wifi state timeout", true);
- } else {
- return;
- }
- }
- Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
- synchronized (cmActivity.wifiObject) {
- try {
- cmActivity.wifiObject.wait(5*1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (cmActivity.mWifiState != expectedState) {
- Log.v(LOG_TAG, "Wifi state is: " + cmActivity.mWifiNetworkInfo.getState());
- continue;
- }
- break;
- }
- }
- }
-
// Test case 1: Test enabling Wifi without associating with any AP
@LargeTest
public void test3GToWifiNotification() {
// To avoid UNKNOWN state when device boots up
cmActivity.enableWifi();
try {
- Thread.sleep(2 * STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -170,7 +113,7 @@
// Eanble Wifi
cmActivity.enableWifi();
try {
- Thread.sleep(2 * STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -208,12 +151,13 @@
assertTrue("failed to connect to " + TEST_ACCESS_POINT,
cmActivity.connectToWifi(TEST_ACCESS_POINT));
- waitForWifiState(WifiManager.WIFI_STATE_ENABLED, STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
Log.v(LOG_TAG, "wifi state is enabled");
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// validate states
if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -237,12 +181,13 @@
// Connect to TEST_ACCESS_POINT
assertTrue("failed to connect to " + TEST_ACCESS_POINT,
cmActivity.connectToWifi(TEST_ACCESS_POINT));
- waitForWifiState(WifiManager.WIFI_STATE_ENABLED, STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
try {
- Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -255,11 +200,12 @@
}
// Wait for the Wifi state to be DISABLED
- waitForWifiState(WifiManager.WIFI_STATE_DISABLED, STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
//Prepare for connectivity state verification
NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
@@ -275,10 +221,10 @@
cmActivity.enableWifi();
// Wait for Wifi to be connected and mobile to be disconnected
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// validate wifi states
if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -298,12 +244,12 @@
assertTrue("failed to connect to " + TEST_ACCESS_POINT,
cmActivity.connectToWifi(TEST_ACCESS_POINT));
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// Wait for a few seconds to avoid the state that both Mobile and Wifi is connected
try {
- Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -318,12 +264,12 @@
NetworkState.TO_DISCONNECTION, State.DISCONNECTED);
// clear Wifi
- cmActivity.clearWifi();
+ cmActivity.removeConfiguredNetworksAndDisableWifi();
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// validate states
if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -357,7 +303,7 @@
// Enable airplane mode
cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
try {
- Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -389,8 +335,8 @@
// disable airplane mode
cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// Validate the state transition
if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
@@ -414,8 +360,8 @@
// Eanble airplane mode
cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
@@ -429,8 +375,8 @@
// Connect to Wifi
assertTrue("failed to connect to " + TEST_ACCESS_POINT,
cmActivity.connectToWifi(TEST_ACCESS_POINT));
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// validate state and broadcast
if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -457,11 +403,11 @@
assertTrue("failed to connect to " + TEST_ACCESS_POINT,
cmActivity.connectToWifi(TEST_ACCESS_POINT));
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
try {
- Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -469,11 +415,11 @@
// Enable airplane mode without clearing Wifi
cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
try {
- Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -487,10 +433,10 @@
// Disable airplane mode
cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
// validate the state transition
if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -508,14 +454,15 @@
//Connect to TEST_ACCESS_POINT
assertTrue("failed to connect to " + TEST_ACCESS_POINT,
cmActivity.connectToWifi(TEST_ACCESS_POINT));
- waitForWifiState(WifiManager.WIFI_STATE_ENABLED, STATE_TRANSITION_LONG_TIMEOUT);
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
assertNotNull("Not associated with any AP",
cmActivity.mWifiManager.getConnectionInfo().getBSSID());
try {
- Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+ Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
} catch (Exception e) {
Log.v(LOG_TAG, "exception: " + e.toString());
}
@@ -527,13 +474,14 @@
}
// Verify the connectivity state for Wifi is DISCONNECTED
- waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
- STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
if (!cmActivity.disableWifi()) {
Log.v(LOG_TAG, "disable Wifi failed");
return;
}
- waitForWifiState(WifiManager.WIFI_STATE_DISABLED, STATE_TRANSITION_LONG_TIMEOUT);
+ assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED,
+ ConnectivityManagerTestActivity.LONG_TIMEOUT));
}
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
new file mode 100644
index 0000000..69eb5db
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.functional;
+
+import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+import com.android.connectivitymanagertest.NetworkState;
+
+import android.R;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test Wi-Fi connection with different configuration
+ * To run this tests:
+ * adb shell am instrument -e class
+ * com.android.connectivitymanagertest.functional.WifiConnectionTest
+ * -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
+ */
+public class WifiConnectionTest
+ extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+ private static final String TAG = "WifiConnectionTest";
+ private static final boolean DEBUG = true;
+ private static final String PKG_NAME = "com.android.connectivitymanagertests";
+ private List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
+ private ConnectivityManagerTestActivity mAct;
+
+ public WifiConnectionTest() {
+ super(PKG_NAME, ConnectivityManagerTestActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mAct = getActivity();
+ networks = mAct.loadNetworkConfigurations();
+ if (DEBUG) {
+ printNetworkConfigurations();
+ }
+
+ // enable Wifi and verify wpa_supplicant is started
+ assertTrue("enable Wifi failed", mAct.enableWifi());
+ try {
+ Thread.sleep( 2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+ } catch (Exception e) {
+ fail("interrupted while waiting for WPA_SUPPLICANT to start");
+ }
+ WifiInfo mConnection = mAct.mWifiManager.getConnectionInfo();
+ assertNotNull(mConnection);
+ assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
+ }
+
+ private void printNetworkConfigurations() {
+ Log.v(TAG, "==== print network configurations parsed from XML file ====");
+ Log.v(TAG, "number of access points: " + networks.size());
+ for (WifiConfiguration config : networks) {
+ Log.v(TAG, config.toString());
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mAct.removeConfiguredNetworksAndDisableWifi();
+ super.tearDown();
+ }
+
+ /**
+ * Connect to the provided Wi-Fi network
+ * @param config is the network configuration
+ * @return true if the connection is successful.
+ */
+ private void connectToWifi(WifiConfiguration config) {
+ // step 1: connect to the test access point
+ assertTrue("failed to connect to " + config.SSID,
+ mAct.connectToWifiWithConfiguration(config));
+
+ // step 2: verify Wifi state and network state;
+ assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+ ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+ assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+ State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+
+ // step 3: verify the current connected network is the given SSID
+ if (DEBUG) {
+ Log.v(TAG, "config.SSID = " + config.SSID);
+ Log.v(TAG, "mAct.mWifiManager.getConnectionInfo.getSSID()" +
+ mAct.mWifiManager.getConnectionInfo().getSSID());
+ }
+ assertTrue(config.SSID.contains(mAct.mWifiManager.getConnectionInfo().getSSID()));
+
+ // Maintain the connection for 50 seconds before switching
+ try {
+ Thread.sleep(50*1000);
+ } catch (Exception e) {
+ fail("interrupted while waiting for WPA_SUPPLICANT to start");
+ }
+ }
+
+ @LargeTest
+ public void testWifiConnections() {
+ for (int i = 0; i < networks.size(); i++) {
+ connectToWifi(networks.get(i));
+ mAct.removeConfiguredNetworksAndDisableWifi();
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index f019599..43cf06a 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -110,6 +110,21 @@
mTestUtils.disable(adapter);
}
+ public void testAcceptPair() {
+ int iterations = BluetoothTestRunner.sPairIterations;
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPairAddress);
+ mTestUtils.enable(adapter);
+
+ for (int i = 0; i < iterations; i++) {
+ mTestUtils.writeOutput("acceptPair iteration " + (i + 1) + " of " + iterations);
+ mTestUtils.acceptPair(adapter, device, BluetoothTestRunner.sPairPasskey,
+ BluetoothTestRunner.sPairPin);
+ mTestUtils.unpair(adapter, device);
+ }
+ mTestUtils.disable(adapter);
+ }
+
public void testConnectA2dp() {
int iterations = BluetoothTestRunner.sConnectA2dpIterations;
if (iterations == 0) {
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 328891c..29dee34 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -137,7 +137,6 @@
@Override
public void onReceive(Context context, Intent intent) {
- Log.i("BT", intent.toString());
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
setFiredFlag(DISCOVERY_STARTED_FLAG);
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
@@ -203,7 +202,7 @@
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
int varient = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, -1);
assertNotSame(-1, varient);
- switch(varient) {
+ switch (varient) {
case BluetoothDevice.PAIRING_VARIANT_PIN:
mDevice.setPin(mPin);
break;
@@ -252,7 +251,7 @@
mDevice = device;
mProfile = profile;
- switch(mProfile) {
+ switch (mProfile) {
case BluetoothProfile.A2DP:
mConnectionAction = BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED;
break;
@@ -384,11 +383,14 @@
mask = 0; // Don't check for received intents since we might have missed them.
break;
case BluetoothAdapter.STATE_OFF:
- case BluetoothAdapter.STATE_TURNING_OFF:
assertFalse(adapter.isEnabled());
start = System.currentTimeMillis();
assertTrue(adapter.enable());
break;
+ case BluetoothAdapter.STATE_TURNING_OFF:
+ start = System.currentTimeMillis();
+ assertTrue(adapter.enable());
+ break;
default:
removeReceiver(receiver);
fail(String.format("enable() invalid state: state=%d", state));
@@ -410,7 +412,6 @@
return;
}
} else {
- assertFalse(adapter.isEnabled());
assertEquals(BluetoothAdapter.STATE_TURNING_ON, state);
}
sleep(POLL_TIME);
@@ -437,7 +438,6 @@
case BluetoothAdapter.STATE_TURNING_ON:
assertFalse(adapter.isEnabled());
start = System.currentTimeMillis();
- assertTrue(adapter.disable());
break;
case BluetoothAdapter.STATE_ON:
assertTrue(adapter.isEnabled());
@@ -470,7 +470,6 @@
return;
}
} else {
- assertFalse(adapter.isEnabled());
assertEquals(BluetoothAdapter.STATE_TURNING_OFF, state);
}
sleep(POLL_TIME);
@@ -629,11 +628,22 @@
}
public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
+ pairOrAcceptPair(adapter, device, passkey, pin, true);
+ }
+
+ public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
+ byte[] pin) {
+ pairOrAcceptPair(adapter, device, passkey, pin, false);
+ }
+
+ private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
+ byte[] pin, boolean pair) {
int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
long start = -1;
+ String methodName = pair ? "pair()" : "acceptPair()";
if (!adapter.isEnabled()) {
- fail("pair() bluetooth not enabled");
+ fail(methodName + " bluetooth not enabled");
}
PairReceiver receiver = getPairReceiver(device, passkey, pin, mask);
@@ -643,7 +653,9 @@
case BluetoothDevice.BOND_NONE:
assertFalse(adapter.getBondedDevices().contains(device));
start = System.currentTimeMillis();
- assertTrue(device.createBond());
+ if (pair) {
+ assertTrue(device.createBond());
+ }
break;
case BluetoothDevice.BOND_BONDING:
mask = 0; // Don't check for received intents since we might have missed them.
@@ -653,7 +665,8 @@
return;
default:
removeReceiver(receiver);
- fail(String.format("pair() invalid state: device=%s, state=%d", device, state));
+ fail(String.format("%s invalid state: device=%s, state=%d", methodName, device,
+ state));
}
long s = System.currentTimeMillis();
@@ -664,10 +677,10 @@
if ((receiver.getFiredFlags() & mask) == mask) {
long finish = receiver.getCompletedTime();
if (start != -1 && finish != -1) {
- writeOutput(String.format("pair() completed in %d ms: device=%s",
+ writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
(finish - start), device));
} else {
- writeOutput(String.format("pair() completed: device=%s", device));
+ writeOutput(String.format("%s completed: device=%s", methodName, device));
}
removeReceiver(receiver);
return;
@@ -678,9 +691,9 @@
int firedFlags = receiver.getFiredFlags();
removeReceiver(receiver);
- fail(String.format("pair() timeout: device=%s, state=%d (expected %d), "
- + "flags=0x%x (expected 0x%x)", device, state, BluetoothDevice.BOND_BONDED,
- firedFlags, mask));
+ fail(String.format("%s timeout: device=%s, state=%d (expected %d), "
+ + "flags=0x%x (expected 0x%x)", methodName, device, state,
+ BluetoothDevice.BOND_BONDED, firedFlags, mask));
}
public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
@@ -788,7 +801,7 @@
long finish = receiver.getCompletedTime();
if (start != -1 && finish != -1) {
writeOutput(String.format("connectProfile() completed in %d ms: "
- +"device=%s, profile=%d", (finish - start), device, profile));
+ + "device=%s, profile=%d", (finish - start), device, profile));
} else {
writeOutput(String.format("connectProfile() completed: device=%s, "
+ "profile=%d", device, profile));
@@ -857,7 +870,7 @@
long finish = receiver.getCompletedTime();
if (start != -1 && finish != -1) {
writeOutput(String.format("disconnectProfile() completed in %d ms: "
- +"device=%s, profile=%d", (finish - start), device, profile));
+ + "device=%s, profile=%d", (finish - start), device, profile));
} else {
writeOutput(String.format("disconnectProfile() completed: device=%s, "
+ "profile=%d", device, profile));
@@ -934,14 +947,12 @@
long s = System.currentTimeMillis();
switch (profile) {
case BluetoothProfile.A2DP:
- while (mA2dp != null
- && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+ while (mA2dp != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
sleep(POLL_TIME);
}
return mA2dp;
case BluetoothProfile.HEADSET:
- while (mHeadset != null
- && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+ while (mHeadset != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
sleep(POLL_TIME);
}
return mHeadset;
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 3d77278..bba7ed7 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -34,7 +34,6 @@
virtual void disconnect() = 0;
- virtual status_t setVideoISurface(const sp<ISurface>& surface) = 0;
virtual status_t setVideoSurface(const sp<Surface>& surface) = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index fa775e7..cb36bbb 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -120,30 +120,6 @@
node_id node,
const char *parameter_name,
OMX_INDEXTYPE *index) = 0;
-
- virtual sp<IOMXRenderer> createRenderer(
- const sp<ISurface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight) = 0;
-
- // Note: These methods are _not_ virtual, it exists as a wrapper around
- // the virtual "createRenderer" method above facilitating extraction
- // of the ISurface from a regular Surface or a java Surface object.
- sp<IOMXRenderer> createRenderer(
- const sp<Surface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight);
-
- sp<IOMXRenderer> createRendererFromJavaSurface(
- JNIEnv *env, jobject javaSurface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight);
};
struct omx_message {
@@ -190,13 +166,6 @@
virtual void onMessage(const omx_message &msg) = 0;
};
-class IOMXRenderer : public IInterface {
-public:
- DECLARE_META_INTERFACE(OMXRenderer);
-
- virtual void render(IOMX::buffer_id buffer) = 0;
-};
-
////////////////////////////////////////////////////////////////////////////////
class BnOMX : public BnInterface<IOMX> {
@@ -213,13 +182,6 @@
uint32_t flags = 0);
};
-class BnOMXRenderer : public BnInterface<IOMXRenderer> {
-public:
- virtual status_t onTransact(
- uint32_t code, const Parcel &data, Parcel *reply,
- uint32_t flags = 0);
-};
-
} // namespace android
#endif // ANDROID_IOMX_H_
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 2d55a55..672931e 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -106,7 +106,6 @@
const KeyedVector<String8, String8> *headers = NULL) = 0;
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
- virtual status_t setVideoISurface(const sp<ISurface>& surface) = 0;
virtual status_t setVideoSurface(const sp<Surface>& surface) = 0;
virtual status_t prepare() = 0;
virtual status_t prepareAsync() = 0;
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index 4fd281b..17908b4 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -19,8 +19,6 @@
#define HARDWARE_API_H_
#include <media/stagefright/OMXPluginBase.h>
-#include <media/stagefright/VideoRenderer.h>
-#include <surfaceflinger/ISurface.h>
#include <ui/android_native_buffer.h>
#include <utils/RefBase.h>
@@ -91,13 +89,6 @@
} // namespace android
-extern android::VideoRenderer *createRenderer(
- const android::sp<android::ISurface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight);
-
extern android::OMXPluginBase *createOMXPlugin();
#endif // HARDWARE_API_H_
diff --git a/include/media/stagefright/VideoRenderer.h b/include/media/stagefright/VideoRenderer.h
deleted file mode 100644
index f80b277..0000000
--- a/include/media/stagefright/VideoRenderer.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef VIDEO_RENDERER_H_
-
-#define VIDEO_RENDERER_H_
-
-#include <sys/types.h>
-
-namespace android {
-
-class VideoRenderer {
-public:
- virtual ~VideoRenderer() {}
-
- virtual void render(
- const void *data, size_t size, void *platformPrivate) = 0;
-
-protected:
- VideoRenderer() {}
-
- VideoRenderer(const VideoRenderer &);
- VideoRenderer &operator=(const VideoRenderer &);
-};
-
-} // namespace android
-
-#endif // VIDEO_RENDERER_H_
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 7f4960f..69b872b 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -434,24 +434,23 @@
}
}
- mMimeType = null;
+ mMimeType = mimeType;
mFileType = 0;
mFileSize = fileSize;
// try mimeType first, if it is specified
if (mimeType != null) {
mFileType = MediaFile.getFileTypeForMimeType(mimeType);
- if (mFileType != 0) {
- mMimeType = mimeType;
- }
}
// if mimeType was not specified, compute file type based on file extension.
- if (mMimeType == null) {
+ if (mFileType == 0) {
MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
if (mediaFileType != null) {
mFileType = mediaFileType.fileType;
- mMimeType = mediaFileType.mimeType;
+ if (mMimeType == null) {
+ mMimeType = mediaFileType.mimeType;
+ }
}
}
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 1a46715..c287c0a 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -29,7 +29,6 @@
enum {
DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
SET_VIDEO_SURFACE,
- SET_VIDEO_ISURFACE,
PREPARE_ASYNC,
START,
STOP,
@@ -65,15 +64,6 @@
remote()->transact(DISCONNECT, data, &reply);
}
- status_t setVideoISurface(const sp<ISurface>& surface)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
- data.writeStrongBinder(surface->asBinder());
- remote()->transact(SET_VIDEO_ISURFACE, data, &reply);
- return reply.readInt32();
- }
-
status_t setVideoSurface(const sp<Surface>& surface)
{
Parcel data, reply;
@@ -245,12 +235,6 @@
disconnect();
return NO_ERROR;
} break;
- case SET_VIDEO_ISURFACE: {
- CHECK_INTERFACE(IMediaPlayer, data, reply);
- sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
- reply->writeInt32(setVideoISurface(surface));
- return NO_ERROR;
- } break;
case SET_VIDEO_SURFACE: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
sp<Surface> surface = Surface::readFromParcel(data);
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index f975217..9ce6738 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -31,48 +31,9 @@
FILL_BUFFER,
EMPTY_BUFFER,
GET_EXTENSION_INDEX,
- CREATE_RENDERER,
OBSERVER_ON_MSG,
- RENDERER_RENDER,
};
-sp<IOMXRenderer> IOMX::createRenderer(
- const sp<Surface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight) {
- return createRenderer(
- surface->getISurface(),
- componentName, colorFormat, encodedWidth, encodedHeight,
- displayWidth, displayHeight);
-}
-
-sp<IOMXRenderer> IOMX::createRendererFromJavaSurface(
- JNIEnv *env, jobject javaSurface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight) {
- jclass surfaceClass = env->FindClass("android/view/Surface");
- if (surfaceClass == NULL) {
- LOGE("Can't find android/view/Surface");
- return NULL;
- }
-
- jfieldID surfaceID = env->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
- if (surfaceID == NULL) {
- LOGE("Can't find Surface.mSurface");
- return NULL;
- }
-
- sp<Surface> surface = (Surface *)env->GetIntField(javaSurface, surfaceID);
-
- return createRenderer(
- surface, componentName, colorFormat, encodedWidth,
- encodedHeight, displayWidth, displayHeight);
-}
-
class BpOMX : public BpInterface<IOMX> {
public:
BpOMX(const sp<IBinder> &impl)
@@ -395,28 +356,6 @@
return err;
}
-
- virtual sp<IOMXRenderer> createRenderer(
- const sp<ISurface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight) {
- Parcel data, reply;
- data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-
- data.writeStrongBinder(surface->asBinder());
- data.writeCString(componentName);
- data.writeInt32(colorFormat);
- data.writeInt32(encodedWidth);
- data.writeInt32(encodedHeight);
- data.writeInt32(displayWidth);
- data.writeInt32(displayHeight);
-
- remote()->transact(CREATE_RENDERER, data, &reply);
-
- return interface_cast<IOMXRenderer>(reply.readStrongBinder());
- }
};
IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
@@ -767,33 +706,6 @@
return OK;
}
- case CREATE_RENDERER:
- {
- CHECK_INTERFACE(IOMX, data, reply);
-
- sp<ISurface> isurface =
- interface_cast<ISurface>(data.readStrongBinder());
-
- const char *componentName = data.readCString();
-
- OMX_COLOR_FORMATTYPE colorFormat =
- static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());
-
- size_t encodedWidth = (size_t)data.readInt32();
- size_t encodedHeight = (size_t)data.readInt32();
- size_t displayWidth = (size_t)data.readInt32();
- size_t displayHeight = (size_t)data.readInt32();
-
- sp<IOMXRenderer> renderer =
- createRenderer(isurface, componentName, colorFormat,
- encodedWidth, encodedHeight,
- displayWidth, displayHeight);
-
- reply->writeStrongBinder(renderer->asBinder());
-
- return OK;
- }
-
default:
return BBinder::onTransact(code, data, reply, flags);
}
@@ -839,44 +751,4 @@
}
}
-////////////////////////////////////////////////////////////////////////////////
-
-class BpOMXRenderer : public BpInterface<IOMXRenderer> {
-public:
- BpOMXRenderer(const sp<IBinder> &impl)
- : BpInterface<IOMXRenderer>(impl) {
- }
-
- virtual void render(IOMX::buffer_id buffer) {
- Parcel data, reply;
- data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
- data.writeIntPtr((intptr_t)buffer);
-
- // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
- // so that the caller knows when to recycle the buffer.
- remote()->transact(RENDERER_RENDER, data, &reply);
- }
-};
-
-IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer");
-
-status_t BnOMXRenderer::onTransact(
- uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
- switch (code) {
- case RENDERER_RENDER:
- {
- CHECK_INTERFACE(IOMXRenderer, data, reply);
-
- IOMX::buffer_id buffer = (void*)data.readIntPtr();
-
- render(buffer);
-
- return NO_ERROR;
- }
-
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
} // namespace android
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 34e41a1..54b292c 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -198,13 +198,6 @@
Mutex::Autolock _l(mLock);
if (mPlayer == 0) return NO_INIT;
- status_t err = mPlayer->setVideoISurface(
- surface == NULL ? NULL : surface->getISurface());
-
- if (err != OK) {
- return err;
- }
-
return mPlayer->setVideoSurface(surface);
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index e84c2dc..00e510b 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -864,14 +864,6 @@
return mStatus;
}
-status_t MediaPlayerService::Client::setVideoISurface(const sp<ISurface>& surface)
-{
- LOGV("[%d] setVideoISurface(%p)", mConnId, surface.get());
- sp<MediaPlayerBase> p = getPlayer();
- if (p == 0) return UNKNOWN_ERROR;
- return p->setVideoISurface(surface);
-}
-
status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface)
{
LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index e197cde..184324c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -206,7 +206,6 @@
// IMediaPlayer interface
virtual void disconnect();
- virtual status_t setVideoISurface(const sp<ISurface>& surface);
virtual status_t setVideoSurface(const sp<Surface>& surface);
virtual status_t prepareAsync();
virtual status_t start();
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 06e4b70..aa8f3f0e 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -35,7 +35,6 @@
const char* path, const KeyedVector<String8, String8> *headers);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoISurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
virtual status_t setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; }
virtual status_t prepare();
virtual status_t prepareAsync();
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index e0957f6..58ef99b 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -44,13 +44,6 @@
return mPlayer->setDataSource(dup(fd), offset, length);
}
-status_t StagefrightPlayer::setVideoISurface(const sp<ISurface> &surface) {
- LOGV("setVideoISurface");
-
- mPlayer->setISurface(surface);
- return OK;
-}
-
status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) {
LOGV("setVideoSurface");
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index 3899447..c4a2588 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -35,7 +35,6 @@
const char *url, const KeyedVector<String8, String8> *headers);
virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoISurface(const sp<ISurface> &surface);
virtual status_t setVideoSurface(const sp<Surface> &surface);
virtual status_t prepare();
virtual status_t prepareAsync();
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 5eaf592..6abd8e3 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -75,9 +75,6 @@
// All the methods below wrap the mPlayer instance.
- virtual status_t setVideoISurface(const android::sp<android::ISurface>& s) {
- return mPlayer->setVideoISurface(s);
- }
virtual status_t setVideoSurface(const android::sp<android::Surface>& s) {
return mPlayer->setVideoSurface(s);
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 41f5f30..ff9f255 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -79,39 +79,16 @@
AwesomeEvent &operator=(const AwesomeEvent &);
};
-struct AwesomeRemoteRenderer : public AwesomeRenderer {
- AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
- : mTarget(target) {
- }
-
- virtual void render(MediaBuffer *buffer) {
- void *id;
- if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
- mTarget->render((IOMX::buffer_id)id);
- }
- }
-
-private:
- sp<IOMXRenderer> mTarget;
-
- AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
- AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
-};
-
struct AwesomeLocalRenderer : public AwesomeRenderer {
AwesomeLocalRenderer(
- bool previewOnly,
- const char *componentName,
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &isurface,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight)
- : mTarget(NULL),
- mLibHandle(NULL) {
- init(previewOnly, componentName,
- colorFormat, isurface, surface, displayWidth,
- displayHeight, decodedWidth, decodedHeight);
+ : mTarget(NULL) {
+ init(colorFormat, surface,
+ displayWidth, displayHeight,
+ decodedWidth, decodedHeight);
}
virtual void render(MediaBuffer *buffer) {
@@ -127,22 +104,13 @@
virtual ~AwesomeLocalRenderer() {
delete mTarget;
mTarget = NULL;
-
- if (mLibHandle) {
- dlclose(mLibHandle);
- mLibHandle = NULL;
- }
}
private:
- VideoRenderer *mTarget;
- void *mLibHandle;
+ SoftwareRenderer *mTarget;
void init(
- bool previewOnly,
- const char *componentName,
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &isurface,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight);
@@ -152,48 +120,13 @@
};
void AwesomeLocalRenderer::init(
- bool previewOnly,
- const char *componentName,
OMX_COLOR_FORMATTYPE colorFormat,
- const sp<ISurface> &isurface,
const sp<Surface> &surface,
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight) {
- if (!previewOnly) {
- // We will stick to the vanilla software-color-converting renderer
- // for "previewOnly" mode, to avoid unneccessarily switching overlays
- // more often than necessary.
-
- mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
-
- if (mLibHandle) {
- typedef VideoRenderer *(*CreateRendererFunc)(
- const sp<ISurface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight);
-
- CreateRendererFunc func =
- (CreateRendererFunc)dlsym(
- mLibHandle,
- "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
- "OMX_COLOR_FORMATTYPEjjjj");
-
- if (func) {
- mTarget =
- (*func)(isurface, componentName, colorFormat,
- displayWidth, displayHeight,
- decodedWidth, decodedHeight);
- }
- }
- }
-
- if (mTarget == NULL) {
- mTarget = new SoftwareRenderer(
- colorFormat, surface, displayWidth, displayHeight,
- decodedWidth, decodedHeight);
- }
+ mTarget = new SoftwareRenderer(
+ colorFormat, surface, displayWidth, displayHeight,
+ decodedWidth, decodedHeight);
}
struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
@@ -867,54 +800,41 @@
}
void AwesomePlayer::initRenderer_l() {
- if (mSurface != NULL || mISurface != NULL) {
- sp<MetaData> meta = mVideoSource->getFormat();
+ if (mSurface == NULL) {
+ return;
+ }
- int32_t format;
- const char *component;
- int32_t decodedWidth, decodedHeight;
- CHECK(meta->findInt32(kKeyColorFormat, &format));
- CHECK(meta->findCString(kKeyDecoderComponent, &component));
- CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
- CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
+ sp<MetaData> meta = mVideoSource->getFormat();
- mVideoRenderer.clear();
+ int32_t format;
+ const char *component;
+ int32_t decodedWidth, decodedHeight;
+ CHECK(meta->findInt32(kKeyColorFormat, &format));
+ CHECK(meta->findCString(kKeyDecoderComponent, &component));
+ CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
+ CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
- // Must ensure that mVideoRenderer's destructor is actually executed
- // before creating a new one.
- IPCThreadState::self()->flushCommands();
+ mVideoRenderer.clear();
- if (mSurface != NULL) {
- if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
- // Hardware decoders avoid the CPU color conversion by decoding
- // directly to ANativeBuffers, so we must use a renderer that
- // just pushes those buffers to the ANativeWindow.
- mVideoRenderer = new AwesomeNativeWindowRenderer(mSurface);
- } else {
- // Other decoders are instantiated locally and as a consequence
- // allocate their buffers in local address space. This renderer
- // then performs a color conversion and copy to get the data
- // into the ANativeBuffer.
- mVideoRenderer = new AwesomeLocalRenderer(
- false, // previewOnly
- component,
- (OMX_COLOR_FORMATTYPE)format,
- mISurface,
- mSurface,
- mVideoWidth, mVideoHeight,
- decodedWidth, decodedHeight);
- }
- } else {
- // Our OMX codecs allocate buffers on the media_server side
- // therefore they require a remote IOMXRenderer that knows how
- // to display them.
- mVideoRenderer = new AwesomeRemoteRenderer(
- mClient.interface()->createRenderer(
- mISurface, component,
- (OMX_COLOR_FORMATTYPE)format,
- decodedWidth, decodedHeight,
- mVideoWidth, mVideoHeight));
- }
+ // Must ensure that mVideoRenderer's destructor is actually executed
+ // before creating a new one.
+ IPCThreadState::self()->flushCommands();
+
+ if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
+ // Hardware decoders avoid the CPU color conversion by decoding
+ // directly to ANativeBuffers, so we must use a renderer that
+ // just pushes those buffers to the ANativeWindow.
+ mVideoRenderer = new AwesomeNativeWindowRenderer(mSurface);
+ } else {
+ // Other decoders are instantiated locally and as a consequence
+ // allocate their buffers in local address space. This renderer
+ // then performs a color conversion and copy to get the data
+ // into the ANativeBuffer.
+ mVideoRenderer = new AwesomeLocalRenderer(
+ (OMX_COLOR_FORMATTYPE)format,
+ mSurface,
+ mVideoWidth, mVideoHeight,
+ decodedWidth, decodedHeight);
}
}
@@ -958,12 +878,6 @@
return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
}
-void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
- Mutex::Autolock autoLock(mLock);
-
- mISurface = isurface;
-}
-
void AwesomePlayer::setSurface(const sp<Surface> &surface) {
Mutex::Autolock autoLock(mLock);
@@ -1897,13 +1811,10 @@
mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
- if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
+ if (state->mLastVideoFrame && mSurface != NULL) {
mVideoRenderer =
new AwesomeLocalRenderer(
- true, // previewOnly
- "",
(OMX_COLOR_FORMATTYPE)state->mColorFormat,
- mISurface,
mSurface,
state->mVideoWidth,
state->mVideoHeight,
diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp
index 39e3e75..f9d27eb 100644
--- a/media/libstagefright/httplive/LiveSource.cpp
+++ b/media/libstagefright/httplive/LiveSource.cpp
@@ -278,7 +278,19 @@
}
if (mLastFetchTimeUs < 0) {
- mPlaylistIndex = 0;
+ if (isSeekable()) {
+ mPlaylistIndex = 0;
+ } else {
+ // This is live streamed content, the first seqnum in the
+ // various bandwidth' streams may be slightly off, so don't
+ // start at the very first entry.
+ // With a segment duration of 6-10secs, this really only
+ // delays playback up to 30secs compared to real time.
+ mPlaylistIndex = 3;
+ if (mPlaylistIndex >= mPlaylist->size()) {
+ mPlaylistIndex = mPlaylist->size() - 1;
+ }
+ }
} else {
if (nextSequenceNumber < mFirstItemSequenceNumber
|| nextSequenceNumber
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 302a1ba..4e63b7a 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -79,7 +79,6 @@
bool isPlaying() const;
- void setISurface(const sp<ISurface> &isurface);
void setSurface(const sp<Surface> &surface);
void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
status_t setLooping(bool shouldLoop);
@@ -130,7 +129,6 @@
bool mQueueStarted;
wp<MediaPlayerBase> mListener;
- sp<ISurface> mISurface;
sp<Surface> mSurface;
sp<MediaPlayerBase::AudioSink> mAudioSink;
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 5a6c96f9..5fed98a 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -97,13 +97,6 @@
const char *parameter_name,
OMX_INDEXTYPE *index);
- virtual sp<IOMXRenderer> createRenderer(
- const sp<ISurface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight);
-
virtual void binderDied(const wp<IBinder> &the_late_who);
OMX_ERRORTYPE OnEvent(
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 8d58056..198bfd6 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -19,15 +19,13 @@
#define SOFTWARE_RENDERER_H_
#include <media/stagefright/ColorConverter.h>
-#include <media/stagefright/VideoRenderer.h>
#include <utils/RefBase.h>
namespace android {
class Surface;
-class MemoryHeapBase;
-class SoftwareRenderer : public VideoRenderer {
+class SoftwareRenderer {
public:
SoftwareRenderer(
OMX_COLOR_FORMATTYPE colorFormat,
@@ -35,9 +33,9 @@
size_t displayWidth, size_t displayHeight,
size_t decodedWidth, size_t decodedHeight);
- virtual ~SoftwareRenderer();
+ ~SoftwareRenderer();
- virtual void render(
+ void render(
const void *data, size_t size, void *platformPrivate);
private:
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index f9f638f..4e9920b 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -24,14 +24,11 @@
#include <sys/resource.h>
#include "../include/OMX.h"
-#include "OMXRenderer.h"
#include "../include/OMXNodeInstance.h"
-#include "../include/SoftwareRenderer.h"
#include <binder/IMemory.h>
#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/VideoRenderer.h>
#include <utils/threads.h>
#include "OMXMaster.h"
@@ -442,110 +439,4 @@
mNodeIDToInstance.removeItem(node);
}
-////////////////////////////////////////////////////////////////////////////////
-
-struct SharedVideoRenderer : public VideoRenderer {
- SharedVideoRenderer(void *libHandle, VideoRenderer *obj)
- : mLibHandle(libHandle),
- mObj(obj) {
- }
-
- virtual ~SharedVideoRenderer() {
- delete mObj;
- mObj = NULL;
-
- dlclose(mLibHandle);
- mLibHandle = NULL;
- }
-
- virtual void render(
- const void *data, size_t size, void *platformPrivate) {
- return mObj->render(data, size, platformPrivate);
- }
-
-private:
- void *mLibHandle;
- VideoRenderer *mObj;
-
- SharedVideoRenderer(const SharedVideoRenderer &);
- SharedVideoRenderer &operator=(const SharedVideoRenderer &);
-};
-
-sp<IOMXRenderer> OMX::createRenderer(
- const sp<ISurface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t encodedWidth, size_t encodedHeight,
- size_t displayWidth, size_t displayHeight) {
- Mutex::Autolock autoLock(mLock);
-
- VideoRenderer *impl = NULL;
-
- void *libHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
-
- if (libHandle) {
- typedef VideoRenderer *(*CreateRendererFunc)(
- const sp<ISurface> &surface,
- const char *componentName,
- OMX_COLOR_FORMATTYPE colorFormat,
- size_t displayWidth, size_t displayHeight,
- size_t decodedWidth, size_t decodedHeight);
-
- CreateRendererFunc func =
- (CreateRendererFunc)dlsym(
- libHandle,
- "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
- "OMX_COLOR_FORMATTYPEjjjj");
-
- if (func) {
- impl = (*func)(surface, componentName, colorFormat,
- displayWidth, displayHeight, encodedWidth, encodedHeight);
-
- if (impl) {
- impl = new SharedVideoRenderer(libHandle, impl);
- libHandle = NULL;
- }
- }
-
- if (libHandle) {
- dlclose(libHandle);
- libHandle = NULL;
- }
- }
-
- if (!impl) {
-#if 0
- LOGW("Using software renderer.");
- impl = new SoftwareRenderer(
- colorFormat,
- surface,
- displayWidth, displayHeight,
- encodedWidth, encodedHeight);
-#else
- CHECK(!"Should not be here.");
- return NULL;
-#endif
- }
-
- return new OMXRenderer(impl);
-}
-
-OMXRenderer::OMXRenderer(VideoRenderer *impl)
- : mImpl(impl) {
-}
-
-OMXRenderer::~OMXRenderer() {
- delete mImpl;
- mImpl = NULL;
-}
-
-void OMXRenderer::render(IOMX::buffer_id buffer) {
- OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
-
- mImpl->render(
- header->pBuffer + header->nOffset,
- header->nFilledLen,
- header->pPlatformPrivate);
-}
-
} // namespace android
diff --git a/media/libstagefright/omx/OMXRenderer.h b/media/libstagefright/omx/OMXRenderer.h
deleted file mode 100644
index 4d194ce..0000000
--- a/media/libstagefright/omx/OMXRenderer.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef OMX_RENDERER_H_
-
-#define OMX_RENDERER_H_
-
-#include <media/IOMX.h>
-
-namespace android {
-
-class VideoRenderer;
-
-class OMXRenderer : public BnOMXRenderer {
-public:
- // Assumes ownership of "impl".
- OMXRenderer(VideoRenderer *impl);
- virtual ~OMXRenderer();
-
- virtual void render(IOMX::buffer_id buffer);
-
-private:
- VideoRenderer *mImpl;
-
- OMXRenderer(const OMXRenderer &);
- OMXRenderer &operator=(const OMXRenderer &);
-};
-
-} // namespace android
-
-#endif // OMX_RENDERER_H_
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index 53308be..1e3731e 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -68,7 +68,6 @@
}
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) {return OK;}
- virtual status_t setVideoISurface(const sp<ISurface>& surface) {return OK;}
virtual status_t setVideoSurface(const sp<Surface>& surface) {return OK;}
virtual status_t prepare() {return OK;}
virtual status_t prepareAsync() {return OK;}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 3dd6510..18815f5 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1832,7 +1832,12 @@
}
final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback);
- ActionMode mode = getCallback().onStartActionMode(wrappedCallback);
+ ActionMode mode = null;
+ try {
+ mode = getCallback().onWindowStartingActionMode(wrappedCallback);
+ } catch (AbstractMethodError ame) {
+ // Older apps might not implement this callback method.
+ }
if (mode != null) {
mActionMode = mode;
} else {
@@ -1876,6 +1881,13 @@
}
}
}
+ if (mActionMode != null) {
+ try {
+ getCallback().onActionModeStarted(mActionMode);
+ } catch (AbstractMethodError ame) {
+ // Older apps might not implement this callback method.
+ }
+ }
return mActionMode;
}
@@ -2091,6 +2103,11 @@
if (mActionModeView != null) {
mActionModeView.removeAllViews();
}
+ try {
+ getCallback().onActionModeFinished(mActionMode);
+ } catch (AbstractMethodError ame) {
+ // Older apps might not implement this callback method.
+ }
mActionMode = null;
}
}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index cd58284..a0a1974 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -7327,16 +7327,22 @@
pw.println(" ");
pw.println("Package warning messages:");
File fname = getSettingsProblemFile();
- FileInputStream in;
+ FileInputStream in = null;
try {
in = new FileInputStream(fname);
int avail = in.available();
byte[] data = new byte[avail];
in.read(data);
pw.print(new String(data));
- in.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
}
}
}
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index 43dbcc0..1a12a84 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -799,8 +799,9 @@
}
private String readFile(String file, char endChar) {
+ FileInputStream is = null;
try {
- FileInputStream is = new FileInputStream(file);
+ is = new FileInputStream(file);
int len = is.read(mBuffer);
is.close();
@@ -815,6 +816,13 @@
}
} catch (java.io.FileNotFoundException e) {
} catch (java.io.IOException e) {
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (java.io.IOException e) {
+ }
+ }
}
return null;
}
@@ -841,4 +849,3 @@
}
}
}
-