summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManagerNative.java21
-rw-r--r--core/java/android/app/ActivityThread.java19
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/ListActivity.java66
-rw-r--r--core/java/android/content/res/Configuration.java21
-rw-r--r--core/java/android/pim/vcard/VCardEntryCommitter.java18
-rw-r--r--core/java/android/provider/Browser.java12
-rw-r--r--core/java/android/provider/ContactsContract.java19
-rw-r--r--core/java/android/provider/Settings.java9
-rw-r--r--core/java/android/text/style/LeadingMarginSpan.java13
-rw-r--r--core/java/android/view/ScaleGestureDetector.java28
-rw-r--r--core/java/android/view/View.java17
-rw-r--r--core/java/android/webkit/WebView.java102
-rw-r--r--core/java/android/webkit/WebViewCore.java9
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java16
-rw-r--r--core/java/com/google/android/util/AbstractMessageParser.java17
-rw-r--r--core/tests/coretests/src/android/text/SpannableStringBuilderTest.java16
-rw-r--r--core/tests/coretests/src/android/text/SpannableStringTest.java16
-rw-r--r--core/tests/coretests/src/android/text/SpannableTest.java16
-rw-r--r--core/tests/coretests/src/android/util/LogTest.java16
-rw-r--r--include/media/stagefright/HTTPDataSource.h23
-rw-r--r--media/libstagefright/AwesomePlayer.cpp74
-rw-r--r--media/libstagefright/DataSource.cpp7
-rw-r--r--media/libstagefright/HTTPDataSource.cpp106
-rw-r--r--media/libstagefright/HTTPStream.cpp44
-rw-r--r--media/libstagefright/StagefrightMetadataRetriever.cpp1
-rw-r--r--media/libstagefright/include/AwesomePlayer.h15
-rw-r--r--media/libstagefright/include/HTTPStream.h3
-rw-r--r--media/libstagefright/omx/OMX.cpp7
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java6
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java6
-rw-r--r--services/java/com/android/server/ConnectivityService.java5
-rw-r--r--services/java/com/android/server/PowerManagerService.java20
-rw-r--r--services/java/com/android/server/UiModeManagerService.java69
-rw-r--r--services/java/com/android/server/Watchdog.java6
-rw-r--r--services/java/com/android/server/WifiService.java24
-rw-r--r--services/java/com/android/server/WifiWatchdogService.java14
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java179
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java10
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaConnection.java32
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/EriInfo.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/EriManager.java2
-rw-r--r--test-runner/src/android/test/BundlePrinter.java16
-rw-r--r--test-runner/src/android/test/IsolatedContext.java16
-rw-r--r--test-runner/src/android/test/ProviderTestCase.java16
-rw-r--r--test-runner/src/android/test/ProviderTestCase2.java16
-rw-r--r--test-runner/src/android/test/RenamingDelegatingContext.java18
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java7
-rw-r--r--tools/aapt/Images.cpp26
49 files changed, 922 insertions, 301 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6849fd766035..6d5686a40c33 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -227,6 +227,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case WILL_ACTIVITY_BE_VISIBLE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ boolean res = willActivityBeVisible(token);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
+
case REGISTER_RECEIVER_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
@@ -1360,6 +1369,18 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
+ public boolean willActivityBeVisible(IBinder token) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(WILL_ACTIVITY_BE_VISIBLE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean res = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver,
IntentFilter filter, String perm) throws RemoteException
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7b5b63e1d21a..35d1948d8703 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3095,9 +3095,6 @@ public final class ActivityThread {
r.paused = false;
r.stopped = false;
- if (r.activity.mStartedActivity) {
- r.hideForNow = true;
- }
r.state = null;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
@@ -3132,7 +3129,15 @@ public final class ActivityThread {
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
- if (r.window == null && !a.mFinished && !a.mStartedActivity) {
+ boolean willBeVisible = !a.mStartedActivity;
+ if (!willBeVisible) {
+ try {
+ willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
+ a.getActivityToken());
+ } catch (RemoteException e) {
+ }
+ }
+ if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
@@ -3148,8 +3153,8 @@ public final class ActivityThread {
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
- // window visisble.
- } else if (a.mStartedActivity) {
+ // window visible.
+ } else if (!willBeVisible) {
if (localLOGV) Log.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
@@ -3157,7 +3162,7 @@ public final class ActivityThread {
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
- if (!r.activity.mFinished && !a.mStartedActivity
+ if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
if (DEBUG_CONFIGURATION) Log.v(TAG, "Resuming activity "
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 3913ed5da0a2..14571defc6fa 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -97,6 +97,7 @@ public interface IActivityManager extends IInterface {
public boolean finishActivity(IBinder token, int code, Intent data)
throws RemoteException;
public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
+ public boolean willActivityBeVisible(IBinder token) throws RemoteException;
public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver, IntentFilter filter,
String requiredPermission) throws RemoteException;
@@ -501,4 +502,5 @@ public interface IActivityManager extends IInterface {
int KILL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+102;
int IS_USER_A_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+103;
int START_ACTIVITY_AND_WAIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+104;
+ int WILL_ACTIVITY_BE_VISIBLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+105;
}
diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java
index 4b4cc050dcbe..84a57b526a6d 100644
--- a/core/java/android/app/ListActivity.java
+++ b/core/java/android/app/ListActivity.java
@@ -51,31 +51,31 @@ import android.widget.ListView;
* The following code demonstrates an (ugly) custom screen layout. It has a list
* with a green background, and an alternate red "no data" message.
* </p>
- *
+ *
* <pre>
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
* android:orientation=&quot;vertical&quot;
- * android:layout_width=&quot;match_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;match_parent&quot;
* android:paddingLeft=&quot;8dp&quot;
* android:paddingRight=&quot;8dp&quot;&gt;
- *
+ *
* &lt;ListView android:id=&quot;@id/android:list&quot;
- * android:layout_width=&quot;match_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#00FF00&quot;
* android:layout_weight=&quot;1&quot;
* android:drawSelectorOnTop=&quot;false&quot;/&gt;
- *
+ *
* &lt;TextView id=&quot;@id/android:empty&quot;
- * android:layout_width=&quot;match_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#FF0000&quot;
* android:text=&quot;No data&quot;/&gt;
* &lt;/LinearLayout&gt;
* </pre>
- *
+ *
* <p>
* <strong>Row Layout</strong>
* </p>
@@ -96,27 +96,27 @@ import android.widget.ListView;
* source for the resource two_line_list_item, which displays two data
* fields,one above the other, for each list row.
* </p>
- *
+ *
* <pre>
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;
* android:orientation=&quot;vertical&quot;&gt;
- *
+ *
* &lt;TextView android:id=&quot;@+id/text1&quot;
* android:textSize=&quot;16sp&quot;
* android:textStyle=&quot;bold&quot;
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
- *
+ *
* &lt;TextView android:id=&quot;@+id/text2&quot;
* android:textSize=&quot;16sp&quot;
* android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
* &lt;/LinearLayout&gt;
* </pre>
- *
+ *
* <p>
* You must identify the data bound to each TextView object in this layout. The
* syntax for this is discussed in the next section.
@@ -137,40 +137,40 @@ import android.widget.ListView;
* Contacts provider for all contacts, then binding the Name and Company fields
* to a two line row layout in the activity's ListView.
* </p>
- *
+ *
* <pre>
* public class MyListAdapter extends ListActivity {
- *
+ *
* &#064;Override
* protected void onCreate(Bundle savedInstanceState){
* super.onCreate(savedInstanceState);
- *
+ *
* // We'll define a custom screen layout here (the one shown above), but
* // typically, you could just use the standard ListActivity layout.
* setContentView(R.layout.custom_list_activity_view);
- *
+ *
* // Query for all people contacts using the {@link android.provider.Contacts.People} convenience class.
* // Put a managed wrapper around the retrieved cursor so we don't have to worry about
* // requerying or closing it as the activity changes state.
* mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, null);
* startManagingCursor(mCursor);
- *
- * // Now create a new list adapter bound to the cursor.
+ *
+ * // Now create a new list adapter bound to the cursor.
* // SimpleListAdapter is designed for binding to a Cursor.
* ListAdapter adapter = new SimpleCursorAdapter(
* this, // Context.
- * android.R.layout.two_line_list_item, // Specify the row template to use (here, two columns bound to the two retrieved cursor
+ * android.R.layout.two_line_list_item, // Specify the row template to use (here, two columns bound to the two retrieved cursor
* rows).
* mCursor, // Pass in the cursor to bind to.
* new String[] {People.NAME, People.COMPANY}, // Array of cursor columns to bind to.
* new int[] {android.R.id.text1, android.R.id.text2}); // Parallel array of which template objects to bind to those columns.
- *
+ *
* // Bind to our new adapter.
* setListAdapter(adapter);
* }
* }
* </pre>
- *
+ *
* @see #setListAdapter
* @see android.widget.ListView
*/
@@ -194,13 +194,13 @@ public class ListActivity extends Activity {
mList.focusableViewAvailable(mList);
}
};
-
+
/**
* This method will be called when an item in the list is selected.
* Subclasses should override. Subclasses can call
* getListView().getItemAtPosition(position) if they need to access the
* data associated with the selected item.
- *
+ *
* @param l The ListView where the click happened
* @param v The view that was clicked within the ListView
* @param position The position of the view in the list
@@ -208,11 +208,11 @@ public class ListActivity extends Activity {
*/
protected void onListItemClick(ListView l, View v, int position, long id) {
}
-
+
/**
* Ensures the list view has been created before Activity restores all
* of the view states.
- *
+ *
*@see Activity#onRestoreInstanceState(Bundle)
*/
@Override
@@ -222,9 +222,18 @@ public class ListActivity extends Activity {
}
/**
+ * @see Activity#onDestroy()
+ */
+ @Override
+ protected void onDestroy() {
+ mHandler.removeCallbacks(mRequestFocus);
+ super.onDestroy();
+ }
+
+ /**
* Updates the screen state (current list and other views) when the
* content changes.
- *
+ *
* @see Activity#onContentChanged()
*/
@Override
@@ -262,7 +271,7 @@ public class ListActivity extends Activity {
/**
* Set the currently selected list item to the specified
* position with the adapter's data
- *
+ *
* @param position
*/
public void setSelection(int position) {
@@ -290,7 +299,7 @@ public class ListActivity extends Activity {
ensureList();
return mList;
}
-
+
/**
* Get the ListAdapter associated with this activity's ListView.
*/
@@ -303,7 +312,7 @@ public class ListActivity extends Activity {
return;
}
setContentView(com.android.internal.R.layout.list_content);
-
+
}
private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
@@ -313,4 +322,3 @@ public class ListActivity extends Activity {
}
};
}
-
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 54fc0447e495..65982642d88a 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -597,12 +597,18 @@ public final class Configuration implements Parcelable, Comparable<Configuration
if (n != 0) return n;
n = this.mnc - that.mnc;
if (n != 0) return n;
- n = this.locale.getLanguage().compareTo(that.locale.getLanguage());
- if (n != 0) return n;
- n = this.locale.getCountry().compareTo(that.locale.getCountry());
- if (n != 0) return n;
- n = this.locale.getVariant().compareTo(that.locale.getVariant());
- if (n != 0) return n;
+ if (this.locale == null) {
+ if (that.locale != null) return 1;
+ } else if (that.locale == null) {
+ return -1;
+ } else {
+ n = this.locale.getLanguage().compareTo(that.locale.getLanguage());
+ if (n != 0) return n;
+ n = this.locale.getCountry().compareTo(that.locale.getCountry());
+ if (n != 0) return n;
+ n = this.locale.getVariant().compareTo(that.locale.getVariant());
+ if (n != 0) return n;
+ }
n = this.touchscreen - that.touchscreen;
if (n != 0) return n;
n = this.keyboard - that.keyboard;
@@ -640,7 +646,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public int hashCode() {
return ((int)this.fontScale) + this.mcc + this.mnc
- + this.locale.hashCode() + this.touchscreen
+ + (this.locale != null ? this.locale.hashCode() : 0)
+ + this.touchscreen
+ this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
+ this.navigation + this.navigationHidden
+ this.orientation + this.screenLayout + this.uiMode;
diff --git a/core/java/android/pim/vcard/VCardEntryCommitter.java b/core/java/android/pim/vcard/VCardEntryCommitter.java
index 3cd64b084866..2f99e4a36514 100644
--- a/core/java/android/pim/vcard/VCardEntryCommitter.java
+++ b/core/java/android/pim/vcard/VCardEntryCommitter.java
@@ -19,6 +19,8 @@ import android.content.ContentResolver;
import android.net.Uri;
import android.util.Log;
+import java.util.ArrayList;
+
/**
* <P>
* {@link VCardEntryHandler} implementation which commits the entry to ContentResolver.
@@ -35,7 +37,7 @@ public class VCardEntryCommitter implements VCardEntryHandler {
private final ContentResolver mContentResolver;
private long mTimeToCommit;
- private Uri mLastCreatedUri;
+ private ArrayList<Uri> mCreatedUris = new ArrayList<Uri>();
public VCardEntryCommitter(ContentResolver resolver) {
mContentResolver = resolver;
@@ -52,11 +54,21 @@ public class VCardEntryCommitter implements VCardEntryHandler {
public void onEntryCreated(final VCardEntry contactStruct) {
long start = System.currentTimeMillis();
- mLastCreatedUri = contactStruct.pushIntoContentResolver(mContentResolver);
+ mCreatedUris.add(contactStruct.pushIntoContentResolver(mContentResolver));
mTimeToCommit += System.currentTimeMillis() - start;
}
+ // TODO: Compatibility function to not break the build. Will be removed shortly
+ @Deprecated
public Uri getLastCreatedUri() {
- return mLastCreatedUri;
+ return mCreatedUris.size() == 0 ? null : mCreatedUris.get(mCreatedUris.size() - 1);
+ }
+
+ /**
+ * Returns the list of created Uris. This list should not be modified by the caller as it is
+ * not a clone.
+ */
+ public ArrayList<Uri> getCreatedUris() {
+ return mCreatedUris;
}
} \ No newline at end of file
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index a5c85c12aeb3..4377a2b997f4 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -363,7 +363,7 @@ public class Browser {
str[i] = c.getString(0);
i++;
}
- c.deactivate();
+ c.close();
return str;
} catch (IllegalStateException e) {
return new String[0];
@@ -402,7 +402,7 @@ public class Browser {
if (!c.moveToNext()) break;
}
}
- c.deactivate();
+ c.close();
} catch (IllegalStateException e) {
Log.e(LOGTAG, "truncateHistory", e);
return;
@@ -427,7 +427,7 @@ public class Browser {
null
);
boolean ret = c.moveToFirst();
- c.deactivate();
+ c.close();
return ret;
} catch (IllegalStateException e) {
return false;
@@ -462,7 +462,7 @@ public class Browser {
null,
null);
if (!c.moveToFirst()) {
- c.deactivate();
+ c.close();
return;
}
@@ -489,7 +489,7 @@ public class Browser {
iconDb.releaseIconForPageUrl(url);
}
} while (c.moveToNext());
- c.deactivate();
+ c.close();
if (!firstTime) {
ContentValues map = new ContentValues();
@@ -576,7 +576,7 @@ public class Browser {
} else {
cr.insert(SEARCHES_URI, map);
}
- c.deactivate();
+ c.close();
} catch (IllegalStateException e) {
Log.e(LOGTAG, "addSearchUrl", e);
return;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index c06a1e2245ad..40a408a12ee8 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -887,6 +887,25 @@ public final class ContactsContract {
"as_vcard");
/**
+ * Base {@link Uri} for referencing multiple {@link Contacts} entry,
+ * created by appending {@link #LOOKUP_KEY} using
+ * {@link Uri#withAppendedPath(Uri, String)}. The lookup keys have to be
+ * encoded and joined with the colon (":") seperator. The resulting string
+ * has to be encoded again. Provides
+ * {@link OpenableColumns} columns when queried, or returns the
+ * referenced contact formatted as a vCard when opened through
+ * {@link ContentResolver#openAssetFileDescriptor(Uri, String)}.
+ *
+ * This is private API because we do not have a well-defined way to
+ * specify several entities yet. The format of this Uri might change in the future
+ * or the Uri might be completely removed.
+ *
+ * @hide
+ */
+ public static final Uri CONTENT_MULTI_VCARD_URI = Uri.withAppendedPath(CONTENT_URI,
+ "as_multi_vcard");
+
+ /**
* Builds a {@link #CONTENT_LOOKUP_URI} style {@link Uri} describing the
* requested {@link Contacts} entry.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 873e1a6feed2..503d8b8da1dd 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2900,6 +2900,15 @@ public final class Settings {
*/
public static final String DROPBOX_TAG_PREFIX =
"dropbox:";
+ /**
+ * Lines of logcat to include with system crash/ANR/etc. reports,
+ * as a prefix of the dropbox tag of the report type.
+ * For example, "logcat_for_system_server_anr" controls the lines
+ * of logcat captured with system server ANR reports. 0 to disable.
+ * @hide
+ */
+ public static final String ERROR_LOGCAT_PREFIX =
+ "logcat_for_";
/**
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
index f320701d5454..2f429ffccf62 100644
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ b/core/java/android/text/style/LeadingMarginSpan.java
@@ -68,7 +68,20 @@ extends ParagraphStyle
boolean first, Layout layout);
+ /**
+ * An extended version of {@link LeadingMarginSpan}, which allows
+ * the implementor to specify the number of lines of text to which
+ * this object is attached that the "first line of paragraph" margin
+ * width will be applied to.
+ */
public interface LeadingMarginSpan2 extends LeadingMarginSpan, WrapTogetherSpan {
+ /**
+ * Returns the number of lines of text to which this object is
+ * attached that the "first line" margin will apply to.
+ * Note that if this returns N, the first N lines of the region,
+ * not the first N lines of each paragraph, will be given the
+ * special margin width.
+ */
public int getLeadingMarginLineCount();
};
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index d8b6d1f47392..ff34f4add39d 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -18,6 +18,7 @@ package android.view;
import android.content.Context;
import android.util.DisplayMetrics;
+import android.util.FloatMath;
/**
* Detects transformation gestures involving more than one pointer ("multitouch")
@@ -96,14 +97,16 @@ public class ScaleGestureDetector {
* A convenience class to extend when you only want to listen for a subset
* of scaling-related events. This implements all methods in
* {@link OnScaleGestureListener} but does nothing.
- * {@link OnScaleGestureListener#onScale(ScaleGestureDetector)} and
- * {@link OnScaleGestureListener#onScaleBegin(ScaleGestureDetector)} return
+ * {@link OnScaleGestureListener#onScale(ScaleGestureDetector)} returns
+ * {@code false} so that a subclass can retrieve the accumulated scale
+ * factor in an overridden onScaleEnd.
+ * {@link OnScaleGestureListener#onScaleBegin(ScaleGestureDetector)} returns
* {@code true}.
*/
public static class SimpleOnScaleGestureListener implements OnScaleGestureListener {
public boolean onScale(ScaleGestureDetector detector) {
- return true;
+ return false;
}
public boolean onScaleBegin(ScaleGestureDetector detector) {
@@ -115,10 +118,19 @@ public class ScaleGestureDetector {
}
}
+ /**
+ * This value is the threshold ratio between our previous combined pressure
+ * and the current combined pressure. We will only fire an onScale event if
+ * the computed ratio between the current and previous event pressures is
+ * greater than this value. When pressure decreases rapidly between events
+ * the position values can often be imprecise, as it usually indicates
+ * that the user is in the process of lifting a pointer off of the device.
+ * Its value was tuned experimentally.
+ */
private static final float PRESSURE_THRESHOLD = 0.67f;
- private Context mContext;
- private OnScaleGestureListener mListener;
+ private final Context mContext;
+ private final OnScaleGestureListener mListener;
private boolean mGestureInProgress;
private MotionEvent mPrevEvent;
@@ -137,7 +149,7 @@ public class ScaleGestureDetector {
private float mPrevPressure;
private long mTimeDelta;
- private float mEdgeSlop;
+ private final float mEdgeSlop;
private float mRightSlopEdge;
private float mBottomSlopEdge;
private boolean mSloppyGesture;
@@ -410,7 +422,7 @@ public class ScaleGestureDetector {
if (mCurrLen == -1) {
final float cvx = mCurrFingerDiffX;
final float cvy = mCurrFingerDiffY;
- mCurrLen = (float)Math.sqrt(cvx*cvx + cvy*cvy);
+ mCurrLen = FloatMath.sqrt(cvx*cvx + cvy*cvy);
}
return mCurrLen;
}
@@ -425,7 +437,7 @@ public class ScaleGestureDetector {
if (mPrevLen == -1) {
final float pvx = mPrevFingerDiffX;
final float pvy = mPrevFingerDiffY;
- mPrevLen = (float)Math.sqrt(pvx*pvx + pvy*pvy);
+ mPrevLen = FloatMath.sqrt(pvx*pvx + pvy*pvy);
}
return mPrevLen;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 54c805fc7984..e83b9b5a53a7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1775,6 +1775,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
private CheckForLongPress mPendingCheckForLongPress;
private CheckForTap mPendingCheckForTap = null;
+ private PerformClick mPerformClick;
private UnsetPressedState mUnsetPressedState;
@@ -4330,7 +4331,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
// Only perform take click actions if we were in the pressed state
if (!focusTaken) {
- performClick();
+ // Use a Runnable and post this rather than calling
+ // performClick directly. This lets other visual state
+ // of the view update before click actions start.
+ if (mPerformClick == null) {
+ mPerformClick = new PerformClick();
+ }
+ if (!post(mPerformClick)) {
+ performClick();
+ }
}
}
@@ -8965,6 +8974,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
}
+ private final class PerformClick implements Runnable {
+ public void run() {
+ performClick();
+ }
+ }
+
/**
* Interface definition for a callback to be invoked when a key event is
* dispatched to this view. The callback will be invoked before the key
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 825ea464186d..c5a4e9eebe6d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -535,9 +535,10 @@ public class WebView extends AbsoluteLayout
static final int SET_ROOT_LAYER_MSG_ID = 124;
static final int RETURN_LABEL = 125;
static final int FIND_AGAIN = 126;
+ static final int CENTER_FIT_RECT = 127;
private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
- private static final int LAST_PACKAGE_MSG_ID = FIND_AGAIN;
+ private static final int LAST_PACKAGE_MSG_ID = CENTER_FIT_RECT;
static final String[] HandlerPrivateDebugString = {
"REMEMBER_PASSWORD", // = 1;
@@ -578,7 +579,8 @@ public class WebView extends AbsoluteLayout
"IMMEDIATE_REPAINT_MSG_ID", // = 123;
"SET_ROOT_LAYER_MSG_ID", // = 124;
"RETURN_LABEL", // = 125;
- "FIND_AGAIN" // = 126;
+ "FIND_AGAIN", // = 126;
+ "CENTER_FIT_RECT" // = 127;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -2301,15 +2303,18 @@ public class WebView extends AbsoluteLayout
scrollBar.draw(canvas);
}
+ private boolean canOverscrollHorizontally() {
+ return (Math.abs(mMinZoomScale - mMaxZoomScale) >= MINIMUM_SCALE_INCREMENT)
+ && getSettings().supportZoom()
+ && getSettings().getUseWideViewPort();
+ }
+
@Override
protected void onOverscrolled(int scrollX, int scrollY, boolean clampedX,
boolean clampedY) {
mInOverScrollMode = false;
int maxX = computeMaxScrollX();
- if (maxX == 0 && (Math.abs(mMinZoomScale - mMaxZoomScale)
- < MINIMUM_SCALE_INCREMENT)
- || !getSettings().supportZoom()
- || !getSettings().getUseWideViewPort()) {
+ if (maxX == 0 && !canOverscrollHorizontally()) {
// do not over scroll x if the page just fits the screen and it
// can't zoom or the view doesn't use wide viewport
scrollX = pinLocX(scrollX);
@@ -3115,6 +3120,14 @@ public class WebView extends AbsoluteLayout
return;
}
+ // if both mContentWidth and mContentHeight are 0, it means there is no
+ // valid Picture passed to WebView yet. This can happen when WebView
+ // just starts. Draw the background and return.
+ if ((mContentWidth | mContentHeight) == 0 && mHistoryPicture == null) {
+ canvas.drawColor(mBackgroundColor);
+ return;
+ }
+
int saveCount = canvas.save();
if (mInOverScrollMode
&& getSettings().getUseSystemOverscrollBackground()) {
@@ -4207,7 +4220,7 @@ public class WebView extends AbsoluteLayout
// Textfields and plugins need to receive the shift up key even if
// another key was released while the shift key was held down.
- if (!inEditingMode() && !nativeFocusIsPlugin()) {
+ if (!inEditingMode() && (mNativeClass == 0 || !nativeFocusIsPlugin())) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
mGotKeyDown = true;
} else {
@@ -5112,8 +5125,10 @@ public class WebView extends AbsoluteLayout
if (ev.getY() < 0) pageUp(true);
return true;
}
+ boolean shiftPressed = mShiftIsPressed && (mNativeClass == 0
+ || !nativeFocusIsPlugin());
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+ if (shiftPressed) {
return true; // discard press if copy in progress
}
mTrackballDown = true;
@@ -5138,7 +5153,7 @@ public class WebView extends AbsoluteLayout
mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
mTrackballDown = false;
mTrackballUpTime = time;
- if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+ if (shiftPressed) {
if (mExtendSelection) {
commitCopy();
} else {
@@ -5276,7 +5291,7 @@ public class WebView extends AbsoluteLayout
float yRate = mTrackballRemainsY * 1000 / elapsed;
int viewWidth = getViewWidth();
int viewHeight = getViewHeight();
- if (mShiftIsPressed && !nativeFocusIsPlugin()) {
+ if (mShiftIsPressed && (mNativeClass == 0 || !nativeFocusIsPlugin())) {
moveSelection(scaleTrackballX(xRate, viewWidth),
scaleTrackballY(yRate, viewHeight));
mTrackballRemainsX = mTrackballRemainsY = 0;
@@ -5314,7 +5329,7 @@ public class WebView extends AbsoluteLayout
+ " mTrackballRemainsX=" + mTrackballRemainsX
+ " mTrackballRemainsY=" + mTrackballRemainsY);
}
- if (nativeFocusIsPlugin()) {
+ if (mNativeClass != 0 && nativeFocusIsPlugin()) {
for (int i = 0; i < count; i++) {
letPluginHandleNavKey(selectKeyCode, time, true);
}
@@ -5381,7 +5396,9 @@ public class WebView extends AbsoluteLayout
vx = 0;
}
}
-
+ if (maxX == 0 && !canOverscrollHorizontally()) {
+ vx = 0;
+ }
if (true /* EMG release: make our fling more like Maps' */) {
// maps cuts their velocity in half
vx = vx * 3 / 4;
@@ -5722,49 +5739,50 @@ public class WebView extends AbsoluteLayout
}
/*
- * Maximize and center the view inside the WebView. If the zoom doesn't need
- * to be changed, do an animated scroll to center it. If the zoom needs to
- * be changed, find the zoom center and do a smooth zoom transition.
+ * Maximize and center the rectangle, specified in the document coordinate
+ * space, inside the WebView. If the zoom doesn't need to be changed, do an
+ * animated scroll to center it. If the zoom needs to be changed, find the
+ * zoom center and do a smooth zoom transition.
*/
- private void centerPluginOnScreen(ViewManager.ChildView child) {
+ private void centerFitRect(int docX, int docY, int docWidth, int docHeight) {
int viewWidth = getViewWidth();
int viewHeight = getViewHeightWithTitle();
- float scale = Math.min((float) viewWidth / child.width,
- (float) viewHeight / child.height);
+ float scale = Math.min((float) viewWidth / docWidth, (float) viewHeight
+ / docHeight);
if (scale < mMinZoomScale) {
scale = mMinZoomScale;
} else if (scale > mMaxZoomScale) {
scale = mMaxZoomScale;
}
if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_INCREMENT) {
- pinScrollTo(
- contentToViewX(child.x + child.width / 2) - viewWidth / 2,
- contentToViewY(child.y + child.height / 2) - viewHeight / 2,
+ pinScrollTo(contentToViewX(docX + docWidth / 2) - viewWidth / 2,
+ contentToViewY(docY + docHeight / 2) - viewHeight / 2,
true, 0);
} else {
- int oldScreenX = contentToViewX(child.x) - mScrollX;
- int newPluginX = (int) (child.x * scale);
- int newPluginWidth = (int) (child.width * scale);
+ int oldScreenX = contentToViewX(docX) - mScrollX;
+ int rectViewX = (int) (docX * scale);
+ int rectViewWidth = (int) (docWidth * scale);
int newMaxWidth = (int) (mContentWidth * scale);
- int newScreenX = (viewWidth - newPluginWidth) / 2;
+ int newScreenX = (viewWidth - rectViewWidth) / 2;
// pin the newX to the WebView
- if (newScreenX > newPluginX) {
- newScreenX = newPluginX;
- } else if (newScreenX > (newMaxWidth - newPluginX - newPluginWidth)) {
- newScreenX = viewWidth - (newMaxWidth - newPluginX);
+ if (newScreenX > rectViewX) {
+ newScreenX = rectViewX;
+ } else if (newScreenX > (newMaxWidth - rectViewX - rectViewWidth)) {
+ newScreenX = viewWidth - (newMaxWidth - rectViewX);
}
mZoomCenterX = (oldScreenX * scale - newScreenX * mActualScale)
/ (scale - mActualScale);
- int oldScreenY = contentToViewY(child.y) - mScrollY;
- int newPluginY = (int) (child.y * scale) + getTitleHeight();
- int newPluginHeight = (int) (child.height * scale);
- int newMaxHeight = (int) (mContentHeight * scale) + getTitleHeight();
- int newScreenY = (viewHeight - newPluginHeight) / 2;
+ int oldScreenY = contentToViewY(docY) - mScrollY;
+ int rectViewY = (int) (docY * scale) + getTitleHeight();
+ int rectViewHeight = (int) (docHeight * scale);
+ int newMaxHeight = (int) (mContentHeight * scale)
+ + getTitleHeight();
+ int newScreenY = (viewHeight - rectViewHeight) / 2;
// pin the newY to the WebView
- if (newScreenY > newPluginY) {
- newScreenY = newPluginY;
- } else if (newScreenY > (newMaxHeight - newPluginY - newPluginHeight)) {
- newScreenY = viewHeight - (newMaxHeight - newPluginY);
+ if (newScreenY > rectViewY) {
+ newScreenY = rectViewY;
+ } else if (newScreenY > (newMaxHeight - rectViewY - rectViewHeight)) {
+ newScreenY = viewHeight - (newMaxHeight - rectViewY);
}
mZoomCenterY = (oldScreenY * scale - newScreenY * mActualScale)
/ (scale - mActualScale);
@@ -5810,7 +5828,7 @@ public class WebView extends AbsoluteLayout
true);
} else {
mInZoomOverview = false;
- centerPluginOnScreen(plugin);
+ centerFitRect(plugin.x, plugin.y, plugin.width, plugin.height);
}
return;
}
@@ -6627,6 +6645,12 @@ public class WebView extends AbsoluteLayout
}
break;
+ case CENTER_FIT_RECT:
+ Rect r = (Rect)msg.obj;
+ mInZoomOverview = false;
+ centerFitRect(r.left, r.top, r.width(), r.height());
+ break;
+
default:
super.handleMessage(msg);
break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 27c720888c5b..a27437845ae5 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2462,6 +2462,15 @@ final class WebViewCore {
}
}
+ // called by JNI
+ private void centerFitRect(int x, int y, int width, int height) {
+ if (mWebView == null) {
+ return;
+ }
+ mWebView.mPrivateHandler.obtainMessage(WebView.CENTER_FIT_RECT,
+ new Rect(x, y, x + width, y + height)).sendToTarget();
+ }
+
private native void nativePause();
private native void nativeResume();
private native void nativeFreeMemory();
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 999b27d114d5..ee2fc121876d 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -1,3 +1,19 @@
+/*
+ * 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.internal.widget;
import android.content.Context;
diff --git a/core/java/com/google/android/util/AbstractMessageParser.java b/core/java/com/google/android/util/AbstractMessageParser.java
index 25f6b3347eb5..1871682ee063 100644
--- a/core/java/com/google/android/util/AbstractMessageParser.java
+++ b/core/java/com/google/android/util/AbstractMessageParser.java
@@ -1,5 +1,18 @@
-// Copyright 2007 The Android Open Source Project
-// All Rights Reserved.
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.google.android.util;
diff --git a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java
index 02c763473286..da920c9a3e2e 100644
--- a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java
+++ b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.text;
import android.text.Spannable;
diff --git a/core/tests/coretests/src/android/text/SpannableStringTest.java b/core/tests/coretests/src/android/text/SpannableStringTest.java
index e9a328174723..8dd12146ea66 100644
--- a/core/tests/coretests/src/android/text/SpannableStringTest.java
+++ b/core/tests/coretests/src/android/text/SpannableStringTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.text;
import android.text.Spannable;
diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java
index 8e7891287d23..46be99d5c775 100644
--- a/core/tests/coretests/src/android/text/SpannableTest.java
+++ b/core/tests/coretests/src/android/text/SpannableTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.text;
import android.test.InstrumentationTestCase;
diff --git a/core/tests/coretests/src/android/util/LogTest.java b/core/tests/coretests/src/android/util/LogTest.java
index 41947d7214da..30c81b0c7228 100644
--- a/core/tests/coretests/src/android/util/LogTest.java
+++ b/core/tests/coretests/src/android/util/LogTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.util;
import junit.framework.Assert;
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index 23522bd0b882..b6176eb374d5 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -20,6 +20,7 @@
#include <media/stagefright/DataSource.h>
#include <utils/String8.h>
+#include <utils/threads.h>
namespace android {
@@ -35,6 +36,9 @@ public:
const char *uri,
const KeyedVector<String8, String8> *headers = NULL);
+ status_t connect();
+ void disconnect();
+
virtual status_t initCheck() const;
virtual ssize_t readAt(off_t offset, void *data, size_t size);
@@ -53,8 +57,21 @@ private:
kBufferSize = 32 * 1024
};
+ enum State {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED
+ };
+
+ State mState;
+ mutable Mutex mStateLock;
+
String8 mHeaders;
+ String8 mStartingHost;
+ String8 mStartingPath;
+ int mStartingPort;
+
HTTPStream *mHttp;
char *mHost;
int mPort;
@@ -67,11 +84,7 @@ private:
bool mContentLengthValid;
unsigned long long mContentLength;
- status_t mInitCheck;
-
- void init(
- const char *_host, int port, const char *_path,
- const KeyedVector<String8, String8> *headers);
+ void init(const KeyedVector<String8, String8> *headers);
ssize_t sendRangeRequest(size_t offset);
void initHeaders(const KeyedVector<String8, String8> *overrides);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e00ba47098d9..10b7be349103 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -26,6 +26,7 @@
#include <binder/IPCThreadState.h>
#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/CachingDataSource.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaBuffer.h>
@@ -318,6 +319,14 @@ void AwesomePlayer::reset() {
}
void AwesomePlayer::reset_l() {
+ if (mFlags & PREPARING) {
+ mFlags |= PREPARE_CANCELLED;
+ if (mConnectingDataSource != NULL) {
+ LOGI("interrupting the connection process");
+ mConnectingDataSource->disconnect();
+ }
+ }
+
while (mFlags & PREPARING) {
mPreparedCondition.wait(mLock);
}
@@ -337,6 +346,12 @@ void AwesomePlayer::reset_l() {
// If we did this later, audio would continue playing while we
// shutdown the video-related resources and the player appear to
// not be as responsive to a reset request.
+ if (mAudioPlayer == NULL && mAudioSource != NULL) {
+ // If we had an audio player, it would have effectively
+ // taken possession of the audio source and stopped it when
+ // _it_ is stopped. Otherwise this is still our responsibility.
+ mAudioSource->stop();
+ }
mAudioSource.clear();
if (mTimeSource != mAudioPlayer) {
@@ -1039,8 +1054,29 @@ status_t AwesomePlayer::prepareAsync_l() {
}
status_t AwesomePlayer::finishSetDataSource_l() {
- sp<DataSource> dataSource =
- DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+ sp<DataSource> dataSource;
+
+ if (!strncasecmp("http://", mUri.string(), 7)) {
+ mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
+
+ mLock.unlock();
+ status_t err = mConnectingDataSource->connect();
+ mLock.lock();
+
+ if (err != OK) {
+ mConnectingDataSource.clear();
+
+ LOGI("mConnectingDataSource->connect() returned %d", err);
+ return err;
+ }
+
+ dataSource = new CachingDataSource(
+ mConnectingDataSource, 32 * 1024, 20);
+
+ mConnectingDataSource.clear();
+ } else {
+ dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+ }
if (dataSource == NULL) {
return UNKNOWN_ERROR;
@@ -1067,7 +1103,7 @@ void AwesomePlayer::abortPrepare(status_t err) {
}
mPrepareResult = err;
- mFlags &= ~PREPARING;
+ mFlags &= ~(PREPARING|PREPARE_CANCELLED);
mAsyncPrepareEvent = NULL;
mPreparedCondition.broadcast();
}
@@ -1078,6 +1114,12 @@ void AwesomePlayer::onPrepareAsyncEvent() {
{
Mutex::Autolock autoLock(mLock);
+ if (mFlags & PREPARE_CANCELLED) {
+ LOGI("prepare was cancelled before doing anything");
+ abortPrepare(UNKNOWN_ERROR);
+ return;
+ }
+
if (mUri.size() > 0) {
status_t err = finishSetDataSource_l();
@@ -1109,7 +1151,19 @@ void AwesomePlayer::onPrepareAsyncEvent() {
}
if (prefetcher != NULL) {
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (mFlags & PREPARE_CANCELLED) {
+ LOGI("prepare was cancelled before preparing the prefetcher");
+ abortPrepare(UNKNOWN_ERROR);
+ return;
+ }
+ }
+
+ LOGI("calling prefetcher->prepare()");
prefetcher->prepare();
+ LOGV("prefetcher is done preparing");
+
prefetcher.clear();
}
@@ -1126,20 +1180,28 @@ void AwesomePlayer::onPrepareAsyncEvent() {
}
mPrepareResult = OK;
- mFlags &= ~PREPARING;
+ mFlags &= ~(PREPARING|PREPARE_CANCELLED);
mFlags |= PREPARED;
mAsyncPrepareEvent = NULL;
mPreparedCondition.broadcast();
}
status_t AwesomePlayer::suspend() {
- LOGI("suspend");
+ LOGV("suspend");
Mutex::Autolock autoLock(mLock);
if (mSuspensionState != NULL) {
return INVALID_OPERATION;
}
+ if (mFlags & PREPARING) {
+ mFlags |= PREPARE_CANCELLED;
+ if (mConnectingDataSource != NULL) {
+ LOGI("interrupting the connection process");
+ mConnectingDataSource->disconnect();
+ }
+ }
+
while (mFlags & PREPARING) {
mPreparedCondition.wait(mLock);
}
@@ -1180,7 +1242,7 @@ status_t AwesomePlayer::suspend() {
}
status_t AwesomePlayer::resume() {
- LOGI("resume");
+ LOGV("resume");
Mutex::Autolock autoLock(mLock);
if (mSuspensionState == NULL) {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 8468a07dd6d8..284e3bc47020 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -101,8 +101,11 @@ sp<DataSource> DataSource::CreateFromURI(
if (!strncasecmp("file://", uri, 7)) {
source = new FileSource(uri + 7);
} else if (!strncasecmp("http://", uri, 7)) {
- source = new HTTPDataSource(uri, headers);
- source = new CachingDataSource(source, 32 * 1024, 20);
+ sp<HTTPDataSource> httpSource = new HTTPDataSource(uri, headers);
+ if (httpSource->connect() != OK) {
+ return NULL;
+ }
+ source = new CachingDataSource(httpSource, 32 * 1024, 20);
} else {
// Assume it's a filename.
source = new FileSource(uri);
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index d79c1bd04a78..451fc2639ea9 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -126,41 +126,71 @@ HTTPDataSource::HTTPDataSource(
host = string(host, 0, colon - host.c_str());
}
- init(host.c_str(), port, path.c_str(), headers);
+ mStartingHost = host.c_str();
+ mStartingPath = path.c_str();
+ mStartingPort = port;
+
+ init(headers);
}
HTTPDataSource::HTTPDataSource(
const char *_host, int port, const char *_path,
const KeyedVector<String8, String8> *headers) {
- init(_host, port, _path, headers);
+ mStartingHost = _host;
+ mStartingPath = _path;
+ mStartingPort = port;
+
+ init(headers);
}
-void HTTPDataSource::init(
- const char *_host, int port, const char *_path,
- const KeyedVector<String8, String8> *headers) {
+void HTTPDataSource::init(const KeyedVector<String8, String8> *headers) {
+ mState = DISCONNECTED;
mHttp = new HTTPStream;
+
mHost = NULL;
mPort = 0;
- mPath = NULL,
+ mPath = NULL;
+
+ initHeaders(headers);
+
mBuffer = malloc(kBufferSize);
mBufferLength = 0;
mBufferOffset = 0;
- mContentLengthValid = false;
+}
- initHeaders(headers);
+status_t HTTPDataSource::connect() {
+ {
+ Mutex::Autolock autoLock(mStateLock);
- string host = _host;
- string path = _path;
+ if (mState != DISCONNECTED) {
+ return ERROR_ALREADY_CONNECTED;
+ }
+
+ mState = CONNECTING;
+ }
+
+ mContentLengthValid = false;
+
+ string host = mStartingHost.string();
+ string path = mStartingPath.string();
+ int port = mStartingPort;
LOGI("Connecting to host '%s', port %d, path '%s'",
host.c_str(), port, path.c_str());
int numRedirectsRemaining = 5;
do {
- mInitCheck = mHttp->connect(host.c_str(), port);
+ status_t err = mHttp->connect(host.c_str(), port);
- if (mInitCheck != OK) {
- return;
+ if (err != OK) {
+ Mutex::Autolock autoLock(mStateLock);
+
+ if (mState != CONNECTING) {
+ LOGV("connect() cancelled");
+ }
+ mState = DISCONNECTED;
+
+ return err;
}
} while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port)
&& numRedirectsRemaining-- > 0);
@@ -175,17 +205,44 @@ void HTTPDataSource::init(
mHost = strdup(host.c_str());
mPort = port;
mPath = strdup(path.c_str());
+
+ Mutex::Autolock autoLock(mStateLock);
+
+ if (mState != CONNECTING) {
+ // disconnect was called when we had just successfully connected.
+ LOGV("connect() cancelled (we had just succeeded connecting)");
+
+ mHttp->disconnect();
+ return UNKNOWN_ERROR;
+ }
+
+ mState = CONNECTED;
+ return OK;
+}
+
+void HTTPDataSource::disconnect() {
+ Mutex::Autolock autoLock(mStateLock);
+
+ if (mState == CONNECTING || mState == CONNECTED) {
+ mHttp->disconnect();
+ mState = DISCONNECTED;
+ }
}
status_t HTTPDataSource::initCheck() const {
- return mInitCheck;
+ Mutex::Autolock autoLock(mStateLock);
+
+ return (mState == CONNECTED) ? (status_t)OK : ERROR_NOT_CONNECTED;
}
status_t HTTPDataSource::getSize(off_t *size) {
*size = 0;
- if (mInitCheck != OK) {
- return mInitCheck;
+ {
+ Mutex::Autolock autoLock(mStateLock);
+ if (mState != CONNECTED) {
+ return ERROR_NOT_CONNECTED;
+ }
}
if (!mContentLengthValid) {
@@ -198,7 +255,10 @@ status_t HTTPDataSource::getSize(off_t *size) {
}
HTTPDataSource::~HTTPDataSource() {
- mHttp->disconnect();
+ disconnect();
+
+ delete mHttp;
+ mHttp = NULL;
free(mBuffer);
mBuffer = NULL;
@@ -212,9 +272,6 @@ HTTPDataSource::~HTTPDataSource() {
free(mHost);
mHost = NULL;
}
-
- delete mHttp;
- mHttp = NULL;
}
ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
@@ -271,6 +328,13 @@ ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
LOGV("readAt %ld, size %d", offset, size);
+ {
+ Mutex::Autolock autoLock(mStateLock);
+ if (mState != CONNECTED) {
+ return ERROR_NOT_CONNECTED;
+ }
+ }
+
if (offset >= mBufferOffset
&& offset < (off_t)(mBufferOffset + mBufferLength)) {
size_t num_bytes_available = mBufferLength - (offset - mBufferOffset);
@@ -304,7 +368,7 @@ ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
mBufferOffset = offset;
if (mContentLengthValid
- && mBufferOffset + contentLength >= mContentLength) {
+ && mBufferOffset + contentLength >= (off_t)mContentLength) {
// If we never triggered a range request but know the content length,
// make sure to not read more data than there could be, otherwise
// we'd block indefinitely if the server doesn't close the connection.
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index 2c5da686b50e..66eadf68f6a0 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -44,12 +44,19 @@ HTTPStream::~HTTPStream() {
}
status_t HTTPStream::connect(const char *server, int port) {
+ Mutex::Autolock autoLock(mLock);
+
status_t err = OK;
if (mState == CONNECTED) {
return ERROR_ALREADY_CONNECTED;
}
+ struct hostent *ent = gethostbyname(server);
+ if (ent == NULL) {
+ return ERROR_UNKNOWN_HOST;
+ }
+
CHECK_EQ(mSocket, -1);
mSocket = socket(AF_INET, SOCK_STREAM, 0);
@@ -57,11 +64,11 @@ status_t HTTPStream::connect(const char *server, int port) {
return UNKNOWN_ERROR;
}
- struct hostent *ent = gethostbyname(server);
- if (ent == NULL) {
- err = ERROR_UNKNOWN_HOST;
- goto exit1;
- }
+ mState = CONNECTING;
+
+ int s = mSocket;
+
+ mLock.unlock();
struct sockaddr_in addr;
addr.sin_family = AF_INET;
@@ -69,24 +76,31 @@ status_t HTTPStream::connect(const char *server, int port) {
addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
- if (::connect(mSocket, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
- err = ERROR_CANNOT_CONNECT;
- goto exit1;
+ int res = ::connect(s, (const struct sockaddr *)&addr, sizeof(addr));
+
+ mLock.lock();
+
+ if (mState != CONNECTING) {
+ return UNKNOWN_ERROR;
}
- mState = CONNECTED;
+ if (res < 0) {
+ close(mSocket);
+ mSocket = -1;
- return OK;
+ mState = READY;
+ return UNKNOWN_ERROR;
+ }
-exit1:
- close(mSocket);
- mSocket = -1;
+ mState = CONNECTED;
- return err;
+ return OK;
}
status_t HTTPStream::disconnect() {
- if (mState != CONNECTED) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != CONNECTED && mState != CONNECTING) {
return ERROR_NOT_CONNECTED;
}
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index c0cf97cd628a..4679207691f1 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -23,7 +23,6 @@
#include <media/stagefright/ColorConverter.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
-#include <media/stagefright/HTTPDataSource.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MetaData.h>
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 7106524afbb5..32c28c1ddab2 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -22,6 +22,7 @@
#include <media/MediaPlayerInterface.h>
#include <media/stagefright/DataSource.h>
+#include <media/stagefright/HTTPDataSource.h>
#include <media/stagefright/OMXClient.h>
#include <utils/threads.h>
@@ -87,12 +88,13 @@ private:
friend struct AwesomeEvent;
enum Flags {
- PLAYING = 1,
- LOOPING = 2,
- FIRST_FRAME = 4,
- PREPARING = 8,
- PREPARED = 16,
- AT_EOS = 32,
+ PLAYING = 1,
+ LOOPING = 2,
+ FIRST_FRAME = 4,
+ PREPARING = 8,
+ PREPARED = 16,
+ AT_EOS = 32,
+ PREPARE_CANCELLED = 64,
};
mutable Mutex mLock;
@@ -160,6 +162,7 @@ private:
MediaBuffer *mVideoBuffer;
sp<Prefetcher> mPrefetcher;
+ sp<HTTPDataSource> mConnectingDataSource;
struct SuspensionState {
String8 mUri;
diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h
index 43ef614d71a6..5d638f386d45 100644
--- a/media/libstagefright/include/HTTPStream.h
+++ b/media/libstagefright/include/HTTPStream.h
@@ -24,6 +24,7 @@
#include <media/stagefright/MediaErrors.h>
#include <utils/KeyedVector.h>
+#include <utils/threads.h>
namespace android {
@@ -54,10 +55,12 @@ public:
private:
enum State {
READY,
+ CONNECTING,
CONNECTED
};
State mState;
+ Mutex mLock;
int mSocket;
KeyedVector<string, string> mHeaders;
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index ff8757d52851..13cb46046b58 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -19,6 +19,8 @@
#include <utils/Log.h>
#include <dlfcn.h>
+#include <linux/prctl.h>
+#include <sys/resource.h>
#include "../include/OMX.h"
#include "OMXRenderer.h"
@@ -29,6 +31,7 @@
#include <binder/IMemory.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/VideoRenderer.h>
+#include <utils/threads.h>
#include "OMXMaster.h"
@@ -91,6 +94,7 @@ OMX::CallbackDispatcher::~CallbackDispatcher() {
void OMX::CallbackDispatcher::post(const omx_message &msg) {
Mutex::Autolock autoLock(mLock);
+
mQueue.push_back(msg);
mQueueChanged.signal();
}
@@ -112,6 +116,9 @@ void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
}
void OMX::CallbackDispatcher::threadEntry() {
+ setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
+ prctl(PR_SET_NAME, (unsigned long)"OMXCallbackDisp", 0, 0, 0);
+
for (;;) {
omx_message msg;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
index ddf5e0bfaf0e..8489a67052f7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
@@ -49,7 +49,7 @@ public class MediaMimeTest extends ActivityInstrumentationTestCase2<MediaFramewo
private final String TAG = "MediaMimeTest";
private Context mContext;
private final String MP3_FILE = "/sdcard/media_api/music/SHORTMP3.mp3";
- private final String MEDIA_PLAYBACK_NAME = "com.android.music.MediaPlaybackActivity";
+ private final String MEDIA_PLAYBACK_NAME = "com.android.music.MediaPlaybackActivityStarter";
public MediaMimeTest() {
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
@@ -77,7 +77,7 @@ public class MediaMimeTest extends ActivityInstrumentationTestCase2<MediaFramewo
assertMediaPlaybackActivityHandles("audio/mp3");
}
- @MediumTest
+ @Suppress
// Checks the MediaPlaybackActivity handles audio/*.
public void testCheckMediaPlaybackHandlesAudio() throws Exception {
assertMediaPlaybackActivityHandles("audio/*");
@@ -86,7 +86,7 @@ public class MediaMimeTest extends ActivityInstrumentationTestCase2<MediaFramewo
// TODO: temporarily remove from medium suite because it hangs whole suite
// @MediumTest
// Checks the MediaPlaybackActivity handles application/itunes. Some servers
- // set the Content-type header to application/iTunes (with capital T, but
+ // set the Content-type hadb ieader to application/iTunes (with capital T, but
// the download manager downcasts it) for their MP3 podcasts. This is non
// standard but we try to support it anyway.
// See bug 1401491
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index a3bbb7447f7a..8202efd9b211 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -395,10 +395,10 @@ public class MediaPlayerPerformance extends ActivityInstrumentationTestCase<Medi
Thread.sleep(10000);
mEndPid = getMediaserverPid();
int memDiff = mEndMemory - startMemory;
- if (memDiff < 0)
+ if (memDiff < 0) {
memDiff = 0;
- else
- output.write("The total diff = " + memDiff);
+ }
+ output.write("The total diff = " + memDiff);
output.write("\n\n");
// mediaserver crash
if (startPid != mEndPid) {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index fc20d969238e..81b8d40b0a37 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -81,8 +81,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
private List mNetRequestersPids[];
- private WifiWatchdogService mWifiWatchdogService;
-
// priority order of the nettrackers
// (excluding dynamically set mNetworkPreference)
// TODO - move mNetworkTypePreference into this
@@ -298,11 +296,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
WifiStateTracker wst = new WifiStateTracker(context, mHandler);
WifiService wifiService = new WifiService(context, wst);
ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
+ wifiService.startWifi();
mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
wst.startMonitoring();
- // Constructing this starts it too
- mWifiWatchdogService = new WifiWatchdogService(context, wst);
break;
case ConnectivityManager.TYPE_MOBILE:
mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler,
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index fc6bfcd72a90..d72416d8206b 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2205,32 +2205,28 @@ class PowerManagerService extends IPowerManager.Stub
if (mHandler == null || !ActivityManagerNative.isSystemReady()) {
throw new IllegalStateException("Too early to call reboot()");
}
-
+
final String finalReason = reason;
Runnable runnable = new Runnable() {
public void run() {
synchronized (this) {
ShutdownThread.reboot(mContext, finalReason, false);
- // if we get here we failed
- notify();
}
}
};
-
+ // ShutdownThread must run on a looper capable of displaying the UI.
mHandler.post(runnable);
- // block until we reboot or fail.
- // throw an exception if we failed to reboot
+ // PowerManager.reboot() is documented not to return so just wait for the inevitable.
synchronized (runnable) {
- try {
- runnable.wait();
- } catch (InterruptedException e) {
+ while (true) {
+ try {
+ runnable.wait();
+ } catch (InterruptedException e) {
+ }
}
}
-
- // if we get here we failed
- throw new IllegalStateException("unable to reboot!");
}
/**
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 8103d7cee64a..84790caf7880 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -52,6 +52,7 @@ import android.util.Slog;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Iterator;
import com.android.internal.R;
import com.android.internal.app.DisableCarModeActivity;
@@ -76,10 +77,10 @@ class UiModeManagerService extends IUiModeManager.Stub {
private final Context mContext;
final Object mLock = new Object();
-
+
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
-
+
private int mNightMode = UiModeManager.MODE_NIGHT_NO;
private boolean mCarModeEnabled = false;
private boolean mCharging = false;
@@ -89,10 +90,10 @@ class UiModeManagerService extends IUiModeManager.Stub {
private boolean mComputedNightMode;
private int mCurUiMode = 0;
private int mSetUiMode = 0;
-
+
private boolean mHoldingConfiguration = false;
private Configuration mConfiguration = new Configuration();
-
+
private boolean mSystemReady;
private NotificationManager mNotificationManager;
@@ -138,7 +139,7 @@ class UiModeManagerService extends IUiModeManager.Stub {
Slog.w(TAG, e.getCause());
}
}
-
+
if (mHoldingConfiguration) {
mHoldingConfiguration = false;
updateConfigurationLocked();
@@ -255,7 +256,7 @@ class UiModeManagerService extends IUiModeManager.Stub {
mContext = context;
ServiceManager.addService(Context.UI_MODE_SERVICE, this);
-
+
mAlarmManager =
(AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
mLocationManager =
@@ -304,7 +305,7 @@ class UiModeManagerService extends IUiModeManager.Stub {
return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
}
}
-
+
public void setNightMode(int mode) throws RemoteException {
synchronized (mLock) {
switch (mode) {
@@ -318,18 +319,18 @@ class UiModeManagerService extends IUiModeManager.Stub {
if (!isDoingNightMode()) {
return;
}
-
+
if (mNightMode != mode) {
mNightMode = mode;
updateLocked();
}
}
}
-
+
public int getNightMode() throws RemoteException {
return mNightMode;
}
-
+
void systemReady() {
synchronized (mLock) {
mSystemReady = true;
@@ -342,7 +343,7 @@ class UiModeManagerService extends IUiModeManager.Stub {
boolean isDoingNightMode() {
return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
}
-
+
void setCarModeLocked(boolean enabled) {
if (mCarModeEnabled != enabled) {
mCarModeEnabled = enabled;
@@ -399,12 +400,12 @@ class UiModeManagerService extends IUiModeManager.Stub {
uiMode = Configuration.UI_MODE_TYPE_NORMAL |
Configuration.UI_MODE_NIGHT_NO;
}
-
+
mCurUiMode = uiMode;
-
+
if (!mHoldingConfiguration && uiMode != mSetUiMode) {
mSetUiMode = uiMode;
-
+
try {
final IActivityManager am = ActivityManagerNative.getDefault();
mConfiguration.uiMode = uiMode;
@@ -414,10 +415,10 @@ class UiModeManagerService extends IUiModeManager.Stub {
}
}
}
-
+
final void updateLocked() {
long ident = Binder.clearCallingIdentity();
-
+
try {
String action = null;
String oldAction = null;
@@ -426,11 +427,11 @@ class UiModeManagerService extends IUiModeManager.Stub {
} else if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_DESK) {
oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
}
-
+
if (mCarModeEnabled) {
if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_CAR) {
adjustStatusBarCarModeLocked();
-
+
if (oldAction != null) {
mContext.sendBroadcast(new Intent(oldAction));
}
@@ -449,11 +450,11 @@ class UiModeManagerService extends IUiModeManager.Stub {
if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
adjustStatusBarCarModeLocked();
}
-
+
mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
action = oldAction;
}
-
+
if (action != null) {
// Send the ordered broadcast; the result receiver will receive after all
// broadcasts have been sent. If any broadcast receiver changes the result
@@ -468,7 +469,7 @@ class UiModeManagerService extends IUiModeManager.Stub {
// the broacast and started the home activity.
mHoldingConfiguration = true;
}
-
+
updateConfigurationLocked();
// keep screen on when charging and in car mode
@@ -609,14 +610,18 @@ class UiModeManagerService extends IUiModeManager.Stub {
}
private void retrieveLocation() {
- Location location;
- Criteria criteria = new Criteria();
- criteria.setSpeedRequired(false);
- criteria.setAltitudeRequired(false);
- criteria.setBearingRequired(false);
- criteria.setAccuracy(Criteria.ACCURACY_FINE);
- final String bestProvider = mLocationManager.getBestProvider(criteria, true);
- location = mLocationManager.getLastKnownLocation(bestProvider);
+ Location location = null;
+ final Iterator<String> providers =
+ mLocationManager.getProviders(new Criteria(), true).iterator();
+ while (providers.hasNext()) {
+ final Location lastKnownLocation =
+ mLocationManager.getLastKnownLocation(providers.next());
+ // pick the most recent location
+ if (location == null || (lastKnownLocation != null &&
+ location.getTime() < lastKnownLocation.getTime())) {
+ location = lastKnownLocation;
+ }
+ }
// In the case there is no location available (e.g. GPS fix or network location
// is not available yet), the longitude of the location is estimated using the timezone,
// latitude and accuracy are set to get a good average.
@@ -684,18 +689,18 @@ class UiModeManagerService extends IUiModeManager.Stub {
mComputedNightMode = nightMode;
}
-
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
-
+
pw.println("Permission Denial: can't dump uimode service from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
-
+
synchronized (mLock) {
pw.println("Current UI Mode Service state:");
pw.print(" mDockState="); pw.print(mDockState);
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 3f64b25796df..be1d1c4cf064 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -828,7 +828,13 @@ public class Watchdog extends Thread {
ArrayList pids = new ArrayList();
pids.add(Process.myPid());
+ if (mPhonePid > 0) pids.add(mPhonePid);
File stack = ActivityManagerService.dumpStackTraces(pids);
+
+ // Give some extra time to make sure the stack traces get written.
+ // The system's been hanging for a minute, another second or two won't hurt much.
+ SystemClock.sleep(2000);
+
mActivity.addErrorToDropBox("watchdog", null, null, null, name, null, stack, null);
// Only kill the process if the debugger is not attached.
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 248f5798ee16..97a43294f967 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -124,6 +124,7 @@ public class WifiService extends IWifiManager.Stub {
private INetworkManagementService nwService;
ConnectivityManager mCm;
+ private WifiWatchdogService mWifiWatchdogService = null;
private String[] mWifiRegexs;
/**
@@ -217,8 +218,6 @@ public class WifiService extends IWifiManager.Stub {
mWifiStateTracker.setWifiState(WIFI_STATE_DISABLED);
mWifiApState = WIFI_AP_STATE_DISABLED;
- boolean wifiEnabled = getPersistedWifiEnabled();
- boolean wifiAPEnabled = wifiEnabled ? false : getPersistedWifiApEnabled();
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
@@ -240,9 +239,6 @@ public class WifiService extends IWifiManager.Stub {
}
);
- Slog.i(TAG, "WifiService starting up with Wi-Fi " +
- (wifiEnabled ? "enabled" : "disabled"));
-
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
@@ -267,7 +263,17 @@ public class WifiService extends IWifiManager.Stub {
}
},new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
+ }
+ /**
+ * Check if Wi-Fi needs to be enabled and start
+ * if needed
+ */
+ public void startWifi() {
+ boolean wifiEnabled = getPersistedWifiEnabled();
+ boolean wifiAPEnabled = wifiEnabled ? false : getPersistedWifiApEnabled();
+ Slog.i(TAG, "WifiService starting up with Wi-Fi " +
+ (wifiEnabled ? "enabled" : "disabled"));
setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());
setWifiApEnabledBlocking(wifiAPEnabled, true, Process.myUid(), null);
}
@@ -446,6 +452,7 @@ public class WifiService extends IWifiManager.Stub {
registerForBroadcasts();
mWifiStateTracker.startEventLoop();
+
} else {
mContext.unregisterReceiver(mReceiver);
@@ -1803,6 +1810,9 @@ public class WifiService extends IWifiManager.Stub {
switch (msg.what) {
case MESSAGE_ENABLE_WIFI:
+ if (mWifiWatchdogService == null) {
+ mWifiWatchdogService = new WifiWatchdogService(mContext, mWifiStateTracker);
+ }
setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);
sWakeLock.release();
break;
@@ -1821,6 +1831,10 @@ public class WifiService extends IWifiManager.Stub {
// a non-zero msg.arg1 value means the "enabled" setting
// should be persisted
setWifiEnabledBlocking(false, msg.arg1 == 1, msg.arg2);
+ if (mWifiWatchdogService != null) {
+ mWifiWatchdogService.quit();
+ mWifiWatchdogService = null;
+ }
sWakeLock.release();
break;
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index e50b317a9992..e2c523ddfd4e 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -89,6 +89,8 @@ public class WifiWatchdogService {
*/
private WifiWatchdogHandler mHandler;
+ private ContentObserver mContentObserver;
+
/**
* The current watchdog state. Only written from the main thread!
*/
@@ -132,7 +134,7 @@ public class WifiWatchdogService {
ContentResolver contentResolver = mContext.getContentResolver();
contentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), false,
- new ContentObserver(mHandler) {
+ mContentObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
if (isWatchdogEnabled()) {
@@ -272,6 +274,16 @@ public class WifiWatchdogService {
}
/**
+ * Unregister broadcasts and quit the watchdog thread
+ */
+ public void quit() {
+ unregisterForWifiBroadcasts();
+ mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+ mHandler.removeAllActions();
+ mHandler.getLooper().quit();
+ }
+
+ /**
* Waits for the main watchdog thread to create the handler.
*/
private void waitForHandlerCreation() {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f6289ae3abb6..b6064e816086 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -111,6 +111,7 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
@@ -4267,6 +4268,22 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ public boolean willActivityBeVisible(IBinder token) {
+ synchronized(this) {
+ int i;
+ for (i=mHistory.size()-1; i>=0; i--) {
+ HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ if (r == token) {
+ return true;
+ }
+ if (r.fullscreen && !r.finishing) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
public void overridePendingTransition(IBinder token, String packageName,
int enterAnim, int exitAnim) {
synchronized(this) {
@@ -4708,7 +4725,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
HistoryRecord parent, final String annotation) {
- if (app.notResponding || app.crashing) {
+ // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
+ if (mShuttingDown || app.notResponding || app.crashing) {
return;
}
@@ -8959,77 +8977,122 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
* @param crashInfo giving an application stack trace, null if absent
*/
public void addErrorToDropBox(String eventType,
- ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
- String subject, String report, File logFile,
- ApplicationErrorReport.CrashInfo crashInfo) {
+ ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
+ final String report, final File logFile,
+ final ApplicationErrorReport.CrashInfo crashInfo) {
// NOTE -- this must never acquire the ActivityManagerService lock,
// otherwise the watchdog may be prevented from resetting the system.
- String dropboxTag;
+ String prefix;
if (process == null || process.pid == MY_PID) {
- dropboxTag = "system_server_" + eventType;
+ prefix = "system_server_";
} else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- dropboxTag = "system_app_" + eventType;
+ prefix = "system_app_";
} else {
- dropboxTag = "data_app_" + eventType;
+ prefix = "data_app_";
}
- DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
- if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
- StringBuilder sb = new StringBuilder(1024);
- if (process == null || process.pid == MY_PID) {
- sb.append("Process: system_server\n");
- } else {
- sb.append("Process: ").append(process.processName).append("\n");
- }
- if (process != null) {
- int flags = process.info.flags;
- IPackageManager pm = ActivityThread.getPackageManager();
- sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
- for (String pkg : process.pkgList) {
- sb.append("Package: ").append(pkg);
- try {
- PackageInfo pi = pm.getPackageInfo(pkg, 0);
- if (pi != null) {
- sb.append(" v").append(pi.versionCode);
- if (pi.versionName != null) {
- sb.append(" (").append(pi.versionName).append(")");
- }
+ final String dropboxTag = prefix + eventType;
+ final DropBoxManager dbox = (DropBoxManager)
+ mContext.getSystemService(Context.DROPBOX_SERVICE);
+
+ // Exit early if the dropbox isn't configured to accept this report type.
+ if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
+
+ final StringBuilder sb = new StringBuilder(1024);
+ if (process == null || process.pid == MY_PID) {
+ sb.append("Process: system_server\n");
+ } else {
+ sb.append("Process: ").append(process.processName).append("\n");
+ }
+ if (process != null) {
+ int flags = process.info.flags;
+ IPackageManager pm = ActivityThread.getPackageManager();
+ sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
+ for (String pkg : process.pkgList) {
+ sb.append("Package: ").append(pkg);
+ try {
+ PackageInfo pi = pm.getPackageInfo(pkg, 0);
+ if (pi != null) {
+ sb.append(" v").append(pi.versionCode);
+ if (pi.versionName != null) {
+ sb.append(" (").append(pi.versionName).append(")");
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Error getting package info: " + pkg, e);
}
- sb.append("\n");
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error getting package info: " + pkg, e);
}
+ sb.append("\n");
}
- if (activity != null) {
- sb.append("Activity: ").append(activity.shortComponentName).append("\n");
- }
- if (parent != null && parent.app != null && parent.app.pid != process.pid) {
- sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
- }
- if (parent != null && parent != activity) {
- sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
- }
- if (subject != null) {
- sb.append("Subject: ").append(subject).append("\n");
- }
- sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
- sb.append("\n");
- if (report != null) {
- sb.append(report);
- }
- if (logFile != null) {
- try {
- sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
- } catch (IOException e) {
- Slog.e(TAG, "Error reading " + logFile, e);
+ }
+ if (activity != null) {
+ sb.append("Activity: ").append(activity.shortComponentName).append("\n");
+ }
+ if (parent != null && parent.app != null && parent.app.pid != process.pid) {
+ sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
+ }
+ if (parent != null && parent != activity) {
+ sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
+ }
+ if (subject != null) {
+ sb.append("Subject: ").append(subject).append("\n");
+ }
+ sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
+ sb.append("\n");
+
+ // Do the rest in a worker thread to avoid blocking the caller on I/O
+ // (After this point, we shouldn't access AMS internal data structures.)
+ Thread worker = new Thread("Error dump: " + dropboxTag) {
+ @Override
+ public void run() {
+ if (report != null) {
+ sb.append(report);
}
+ if (logFile != null) {
+ try {
+ sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
+ } catch (IOException e) {
+ Slog.e(TAG, "Error reading " + logFile, e);
+ }
+ }
+ if (crashInfo != null && crashInfo.stackTrace != null) {
+ sb.append(crashInfo.stackTrace);
+ }
+
+ String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
+ int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
+ if (lines > 0) {
+ sb.append("\n");
+
+ // Merge several logcat streams, and take the last N lines
+ InputStreamReader input = null;
+ try {
+ java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
+ "-v", "time", "-b", "events", "-b", "system", "-b", "main",
+ "-t", String.valueOf(lines)).redirectErrorStream(true).start();
+
+ try { logcat.getOutputStream().close(); } catch (IOException e) {}
+ try { logcat.getErrorStream().close(); } catch (IOException e) {}
+ input = new InputStreamReader(logcat.getInputStream());
+
+ int num;
+ char[] buf = new char[8192];
+ while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
+ } catch (IOException e) {
+ Slog.e(TAG, "Error running logcat", e);
+ } finally {
+ if (input != null) try { input.close(); } catch (IOException e) {}
+ }
+ }
+
+ dbox.addText(dropboxTag, sb.toString());
}
- if (crashInfo != null && crashInfo.stackTrace != null) {
- sb.append(crashInfo.stackTrace);
- }
- dbox.addText(dropboxTag, sb.toString());
+ };
+
+ if (process == null || process.pid == MY_PID) {
+ worker.run(); // We may be about to die -- need to run this synchronously
+ } else {
+ worker.start();
}
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 25f123c9be69..ccb5fc6346aa 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -123,17 +123,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
mTetherMasterSM.start();
- // TODO - remove this hack after real USB connections are detected.
+ mStateReceiver = new StateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ mContext.registerReceiver(mStateReceiver, filter);
+
+ filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_SHARED);
filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
+ filter.addDataScheme("file");
+ mContext.registerReceiver(mStateReceiver, filter);
+
mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals(
Environment.getExternalStorageState());
- mStateReceiver = new StateReceiver();
- mContext.registerReceiver(mStateReceiver, filter);
mDhcpRange = context.getResources().getStringArray(
com.android.internal.R.array.config_tether_dhcp_range);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 08946d249356..188145b33fcb 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -592,8 +592,11 @@ public class CdmaConnection extends Connection {
if (!isIncoming) {
// outgoing calls only
processNextPostDialChar();
+ } else {
+ // Only release wake lock for incoming calls, for outgoing calls the wake lock
+ // will be released after any pause-dial is completed
+ releaseWakeLock();
}
- releaseWakeLock();
}
private void
@@ -688,6 +691,7 @@ public class CdmaConnection extends Connection {
Registrant postDialHandler;
if (postDialState == PostDialState.CANCELLED) {
+ releaseWakeLock();
//Log.v("CDMA", "##### processNextPostDialChar: postDialState == CANCELLED, bail");
return;
}
@@ -696,6 +700,9 @@ public class CdmaConnection extends Connection {
postDialString.length() <= nextPostDialChar) {
setPostDialState(PostDialState.COMPLETE);
+ // We were holding a wake lock until pause-dial was complete, so give it up now
+ releaseWakeLock();
+
// notifyMessage.arg1 is 0 on complete
c = 0;
} else {
@@ -770,19 +777,24 @@ public class CdmaConnection extends Connection {
}
/**
- * Set post dial state and acquire wake lock while switching to "started"
- * state, the wake lock will be released if state switches out of "started"
+ * Set post dial state and acquire wake lock while switching to "started" or "wait"
+ * state, the wake lock will be released if state switches out of "started" or "wait"
* state or after WAKE_LOCK_TIMEOUT_MILLIS.
* @param s new PostDialState
*/
private void setPostDialState(PostDialState s) {
- if (postDialState != PostDialState.STARTED
- && s == PostDialState.STARTED) {
- acquireWakeLock();
- Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
- h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
- } else if (postDialState == PostDialState.STARTED
- && s != PostDialState.STARTED) {
+ if (s == PostDialState.STARTED ||
+ s == PostDialState.PAUSE) {
+ synchronized (mPartialWakeLock) {
+ if (mPartialWakeLock.isHeld()) {
+ h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
+ } else {
+ acquireWakeLock();
+ }
+ Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
+ h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
+ }
+ } else {
h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
releaseWakeLock();
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
index 5c8e23e81b4c..3e5d37e39b59 100644
--- a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
+++ b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
@@ -1,4 +1,6 @@
/*
+ * 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
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriManager.java b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
index 37c1d55eec47..1bcc90a07063 100644
--- a/telephony/java/com/android/internal/telephony/cdma/EriManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
@@ -1,4 +1,6 @@
/*
+ * 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
diff --git a/test-runner/src/android/test/BundlePrinter.java b/test-runner/src/android/test/BundlePrinter.java
index 96213e735bac..3c473798ab6a 100644
--- a/test-runner/src/android/test/BundlePrinter.java
+++ b/test-runner/src/android/test/BundlePrinter.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.test;
import java.io.PrintStream;
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index f0935989b545..b483b825fdef 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.test;
import com.google.android.collect.Lists;
diff --git a/test-runner/src/android/test/ProviderTestCase.java b/test-runner/src/android/test/ProviderTestCase.java
index 668e9f7adb11..e1172cf21ff7 100644
--- a/test-runner/src/android/test/ProviderTestCase.java
+++ b/test-runner/src/android/test/ProviderTestCase.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.test;
import android.content.ContentProvider;
diff --git a/test-runner/src/android/test/ProviderTestCase2.java b/test-runner/src/android/test/ProviderTestCase2.java
index f3655fc781dd..28ecee51af0a 100644
--- a/test-runner/src/android/test/ProviderTestCase2.java
+++ b/test-runner/src/android/test/ProviderTestCase2.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.test;
import android.content.ContentProvider;
diff --git a/test-runner/src/android/test/RenamingDelegatingContext.java b/test-runner/src/android/test/RenamingDelegatingContext.java
index 0ea43ab5abe1..973b9f285f95 100644
--- a/test-runner/src/android/test/RenamingDelegatingContext.java
+++ b/test-runner/src/android/test/RenamingDelegatingContext.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.test;
import com.google.android.collect.Sets;
@@ -230,4 +246,4 @@ public class RenamingDelegatingContext extends ContextWrapper {
// }
// return files.toArray(new String[]{});
// }
-} \ No newline at end of file
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index eecd00aa6eea..e3486a0ec92b 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -24,9 +24,8 @@ public class FileFilter {
private static final String LOGTAG = "FileFilter";
// Returns whether we should ignore this test and skip running it.
- // Currently we use this only for tests that crash the browser.
- // TODO: Once these crashes are fixed, we should probably eliminate this
- // method, as no test should crash.
+ // Currently we use this only for tests that crash or hang DumpRenderTree.
+ // TODO: Fix these and eliminate this method.
public static boolean ignoreTest(String file) {
for (int i = 0; i < ignoreTestList.length; i++) {
if (file.endsWith(ignoreTestList[i])) {
@@ -74,6 +73,8 @@ public class FileFilter {
static final String[] ignoreTestList = {
"fast/js/regexp-charclass-crash.html", // RegExp is too large, causing OOM
+ "fast/regex/test1.html", // Causes DumpRenderTree to hang with V8
+ "fast/regex/slow.html", // Causes DumpRenderTree to hang with V8
"editing/selection/move-left-right.html" // Causes DumpRenderTree to hang
};
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index f2414dd85487..3c471ca76107 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -359,7 +359,7 @@ static status_t do_9patch(const char* imageName, image_info* image)
const char* errorMsg = NULL;
int errorPixel = -1;
- const char* errorEdge = "";
+ const char* errorEdge = NULL;
int colorIndex = 0;
@@ -463,6 +463,14 @@ static status_t do_9patch(const char* imageName, image_info* image)
if (yDivs[numYDivs - 1] == H) {
numRows--;
}
+
+ // Make sure the amount of rows and columns will fit in the number of
+ // colors we can use in the 9-patch format.
+ if (numRows * numCols > 0x7F) {
+ errorMsg = "Too many rows and columns in 9-patch perimeter";
+ goto getout;
+ }
+
numColors = numRows * numCols;
image->info9Patch.numColors = numColors;
image->info9Patch.colors = (uint32_t*)malloc(numColors * sizeof(uint32_t));
@@ -533,12 +541,14 @@ getout:
fprintf(stderr,
"ERROR: 9-patch image %s malformed.\n"
" %s.\n", imageName, errorMsg);
- if (errorPixel >= 0) {
- fprintf(stderr,
- " Found at pixel #%d along %s edge.\n", errorPixel, errorEdge);
- } else {
- fprintf(stderr,
- " Found along %s edge.\n", errorEdge);
+ if (errorEdge != NULL) {
+ if (errorPixel >= 0) {
+ fprintf(stderr,
+ " Found at pixel #%d along %s edge.\n", errorPixel, errorEdge);
+ } else {
+ fprintf(stderr,
+ " Found along %s edge.\n", errorEdge);
+ }
}
return UNKNOWN_ERROR;
}
@@ -613,7 +623,7 @@ static void dump_image(int w, int h, png_bytepp rows, int color_type)
} else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
bpp = 2;
} else if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
- // We use a padding byte even when there is no alpha
+ // We use a padding byte even when there is no alpha
bpp = 4;
} else {
printf("Unknown color type %d.\n", color_type);