Merge "Add a fixed viewport margin since website content width changes."
diff --git a/api/current.xml b/api/current.xml
index 27a17e6..89e91ca 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6268,17 +6268,6 @@
visibility="public"
>
</field>
-<field name="kraken_resource_pad57"
- type="int"
- transient="false"
- volatile="false"
- value="16843464"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="kraken_resource_pad6"
type="int"
transient="false"
@@ -10129,6 +10118,17 @@
visibility="public"
>
</field>
+<field name="textSelectHandleWindowStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843464"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="textSize"
type="int"
transient="false"
@@ -15869,6 +15869,28 @@
visibility="public"
>
</field>
+<field name="simple_list_item_activated_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367075"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="simple_list_item_activated_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367076"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="simple_list_item_checked"
type="int"
transient="false"
@@ -22618,7 +22640,7 @@
</implements>
<implements name="android.view.KeyEvent.Callback">
</implements>
-<implements name="android.view.LayoutInflater.Factory">
+<implements name="android.view.LayoutInflater.Factory2">
</implements>
<implements name="android.view.View.OnCreateContextMenuListener">
</implements>
@@ -22751,6 +22773,23 @@
<parameter name="ev" type="android.view.MotionEvent">
</parameter>
</method>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
<method name="findFragmentById"
return="android.app.Fragment"
abstract="false"
@@ -23456,6 +23495,25 @@
<parameter name="attrs" type="android.util.AttributeSet">
</parameter>
</method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
<method name="onDestroy"
return="void"
abstract="false"
@@ -28720,6 +28778,25 @@
visibility="public"
>
</constructor>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
<method name="equals"
return="boolean"
abstract="false"
@@ -28908,6 +28985,17 @@
visibility="public"
>
</method>
+<method name="isInLayout"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="isResumed"
return="boolean"
abstract="false"
@@ -29514,6 +29602,25 @@
visibility="public"
>
</method>
+<method name="dump"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
<method name="findFragmentById"
return="android.app.Fragment"
abstract="true"
@@ -106673,6 +106780,19 @@
<parameter name="value" type="java.lang.String">
</parameter>
</method>
+<method name="setShowRunningNotification"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="show" type="boolean">
+</parameter>
+</method>
<method name="setTitle"
return="android.net.DownloadManager.Request"
abstract="false"
@@ -157148,6 +157268,17 @@
visibility="public"
>
</field>
+<field name="AUTO_TIME_ZONE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""auto_time_zone""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="BLUETOOTH_DISCOVERABILITY"
type="java.lang.String"
transient="false"
@@ -178460,19 +178591,6 @@
<parameter name="event" type="android.view.MotionEvent">
</parameter>
</method>
-<method name="setCursorController"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cursorController" type="android.widget.TextView.CursorController">
-</parameter>
-</method>
</class>
<class name="BaseKeyListener"
extends="android.text.method.MetaKeyKeyListener"
@@ -193168,6 +193286,17 @@
visibility="public"
>
</method>
+<method name="getFactory2"
+ return="android.view.LayoutInflater.Factory2"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getFilter"
return="android.view.LayoutInflater.Filter"
abstract="false"
@@ -193260,6 +193389,25 @@
<exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
</exception>
</method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
+</exception>
+</method>
<method name="setFactory"
return="void"
abstract="false"
@@ -193273,6 +193421,19 @@
<parameter name="factory" type="android.view.LayoutInflater.Factory">
</parameter>
</method>
+<method name="setFactory2"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factory" type="android.view.LayoutInflater.Factory2">
+</parameter>
+</method>
<method name="setFilter"
return="void"
abstract="false"
@@ -193312,6 +193473,35 @@
</parameter>
</method>
</interface>
+<interface name="LayoutInflater.Factory2"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.LayoutInflater.Factory">
+</implements>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
+</interface>
<interface name="LayoutInflater.Filter"
abstract="true"
static="true"
@@ -239242,121 +239432,6 @@
>
</method>
</class>
-<interface name="TextView.CursorController"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="draw"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="canvas" type="android.graphics.Canvas">
-</parameter>
-</method>
-<method name="getOffsetX"
- return="float"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getOffsetY"
- return="float"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="hide"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="isShowing"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onTouchEvent"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="show"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="updatePosition"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="x" type="int">
-</parameter>
-<parameter name="y" type="int">
-</parameter>
-</method>
-<field name="FADE_OUT_DURATION"
- type="int"
- transient="false"
- volatile="false"
- value="400"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</interface>
<interface name="TextView.OnEditorActionListener"
abstract="true"
static="true"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 29db0ec..ee49d97 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -74,6 +74,8 @@
import android.widget.AdapterView;
import android.widget.FrameLayout;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -605,7 +607,7 @@
* or finished.
*/
public class Activity extends ContextThemeWrapper
- implements LayoutInflater.Factory,
+ implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks {
private static final String TAG = "Activity";
@@ -4030,15 +4032,30 @@
* Standard implementation of
* {@link android.view.LayoutInflater.Factory#onCreateView} used when
* inflating with the LayoutInflater returned by {@link #getSystemService}.
+ * This implementation does nothing and is for
+ * pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB} apps. Newer apps
+ * should use {@link #onCreateView(View, String, Context, AttributeSet)}.
+ *
+ * @see android.view.LayoutInflater#createView
+ * @see android.view.Window#getLayoutInflater
+ */
+ public View onCreateView(String name, Context context, AttributeSet attrs) {
+ return null;
+ }
+
+ /**
+ * Standard implementation of
+ * {@link android.view.LayoutInflater.Factory2#onCreateView(View, String, Context, AttributeSet)}
+ * used when inflating with the LayoutInflater returned by {@link #getSystemService}.
* This implementation handles <fragment> tags to embed fragments inside
* of the activity.
*
* @see android.view.LayoutInflater#createView
* @see android.view.Window#getLayoutInflater
*/
- public View onCreateView(String name, Context context, AttributeSet attrs) {
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!"fragment".equals(name)) {
- return null;
+ return onCreateView(name, context, attrs);
}
String fname = attrs.getAttributeValue(null, "class");
@@ -4047,42 +4064,70 @@
if (fname == null) {
fname = a.getString(com.android.internal.R.styleable.Fragment_name);
}
- int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, 0);
+ int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
a.recycle();
- if (id == 0) {
+ int containerId = parent != null ? parent.getId() : 0;
+ if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
throw new IllegalArgumentException(attrs.getPositionDescription()
- + ": Must specify unique android:id for " + fname);
+ + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
}
-
+
// If we restored from a previous state, we may already have
// instantiated this fragment from the state and should use
// that instance instead of making a new one.
- Fragment fragment = mFragments.findFragmentById(id);
+ Fragment fragment = id != View.NO_ID ? mFragments.findFragmentById(id) : null;
+ if (fragment == null && tag != null) {
+ fragment = mFragments.findFragmentByTag(tag);
+ }
+ if (fragment == null && containerId != View.NO_ID) {
+ fragment = mFragments.findFragmentById(containerId);
+ }
+
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
+ Integer.toHexString(id) + " fname=" + fname
+ " existing=" + fragment);
if (fragment == null) {
fragment = Fragment.instantiate(this, fname);
fragment.mFromLayout = true;
- fragment.mFragmentId = id;
+ fragment.mFragmentId = id != 0 ? id : containerId;
+ fragment.mContainerId = containerId;
fragment.mTag = tag;
+ fragment.mInLayout = true;
fragment.mImmediateActivity = this;
fragment.mFragmentManager = mFragments;
+ fragment.onInflate(attrs, fragment.mSavedFragmentState);
+ mFragments.addFragment(fragment, true);
+
+ } else if (fragment.mInLayout) {
+ // A fragment already exists and it is not one we restored from
+ // previous state.
+ throw new IllegalArgumentException(attrs.getPositionDescription()
+ + ": Duplicate id 0x" + Integer.toHexString(id)
+ + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
+ + " with another fragment for " + fname);
+ } else {
+ // This fragment was retained from a previous instance; get it
+ // going now.
+ fragment.mInLayout = true;
+ fragment.mImmediateActivity = this;
// If this fragment is newly instantiated (either right now, or
// from last saved state), then give it the attributes to
// initialize itself.
if (!fragment.mRetaining) {
fragment.onInflate(attrs, fragment.mSavedFragmentState);
}
- mFragments.addFragment(fragment, true);
+ mFragments.moveToState(fragment);
}
+
if (fragment.mView == null) {
throw new IllegalStateException("Fragment " + fname
+ " did not create a view.");
}
- fragment.mView.setId(id);
+ if (id != 0) {
+ fragment.mView.setId(id);
+ }
if (fragment.mView.getTag() == null) {
fragment.mView.setTag(tag);
}
@@ -4090,6 +4135,19 @@
}
/**
+ * Print the Activity's state into the given stream. This gets invoked if
+ * you run "adb shell dumpsys activity <youractivityname>".
+ *
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer The PrintWriter to which you should dump your state. This will be
+ * closed for you after you return.
+ * @param args additional arguments to the dump request.
+ */
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mFragments.dump("", fd, writer, args);
+ }
+
+ /**
* Bit indicating that this activity is "immersive" and should not be
* interrupted by notifications if possible.
*
@@ -4177,7 +4235,7 @@
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
- mWindow.getLayoutInflater().setFactory(this);
+ mWindow.getLayoutInflater().setFactory2(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c0e2987..3f74904 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -335,9 +335,9 @@
}
}
- private static final class DumpServiceInfo {
+ private static final class DumpComponentInfo {
FileDescriptor fd;
- IBinder service;
+ IBinder token;
String[] args;
boolean dumped;
}
@@ -370,7 +370,8 @@
private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%17s %8d";
private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
- private static final String DB_INFO_FORMAT = " %4d %6d %8d %14s %s";
+ private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d";
+ private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
// Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
@@ -591,9 +592,9 @@
}
public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
- DumpServiceInfo data = new DumpServiceInfo();
+ DumpComponentInfo data = new DumpComponentInfo();
data.fd = fd;
- data.service = servicetoken;
+ data.token = servicetoken;
data.args = args;
data.dumped = false;
queueOrSendMessage(H.DUMP_SERVICE, data);
@@ -663,6 +664,25 @@
public void scheduleCrash(String msg) {
queueOrSendMessage(H.SCHEDULE_CRASH, msg);
}
+
+ public void dumpActivity(FileDescriptor fd, IBinder activitytoken, String[] args) {
+ DumpComponentInfo data = new DumpComponentInfo();
+ data.fd = fd;
+ data.token = activitytoken;
+ data.args = args;
+ data.dumped = false;
+ queueOrSendMessage(H.DUMP_ACTIVITY, data);
+ synchronized (data) {
+ while (!data.dumped) {
+ try {
+ data.wait();
+ } catch (InterruptedException e) {
+ // no need to do anything here, we will keep waiting until
+ // dumped is set
+ }
+ }
+ }
+ }
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -820,20 +840,23 @@
// SQLite mem info
pw.println(" ");
pw.println(" SQL");
- printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
+ printRow(pw, TWO_COUNT_COLUMNS_DB, "heap:", sqliteAllocated, "MEMORY_USED:",
stats.memoryUsed / 1024);
- printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
- "largestMemAlloc:", stats.largestMemAlloc / 1024);
+ printRow(pw, TWO_COUNT_COLUMNS_DB, "PAGECACHE_OVERFLOW:",
+ stats.pageCacheOverflo / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
pw.println(" ");
int N = stats.dbStats.size();
if (N > 0) {
pw.println(" DATABASES");
- printRow(pw, " %4s %6s %8s %14s %s", "pgsz", "dbsz", "lkaside", "cache",
- "Dbname");
+ printRow(pw, " %8s %8s %14s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
+ "Dbname");
for (int i = 0; i < N; i++) {
DbStats dbStats = stats.dbStats.get(i);
- printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
- dbStats.lookaside, dbStats.cache, dbStats.dbName);
+ printRow(pw, DB_INFO_FORMAT,
+ (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
+ (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
+ (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
+ dbStats.cache, dbStats.dbName);
}
}
@@ -888,6 +911,7 @@
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
public static final int SCHEDULE_CRASH = 134;
public static final int DUMP_HEAP = 135;
+ public static final int DUMP_ACTIVITY = 136;
String codeToString(int code) {
if (localLOGV) {
switch (code) {
@@ -927,6 +951,7 @@
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
case DUMP_HEAP: return "DUMP_HEAP";
+ case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
}
}
return "(unknown)";
@@ -1021,7 +1046,7 @@
scheduleGcIdler();
break;
case DUMP_SERVICE:
- handleDumpService((DumpServiceInfo)msg.obj);
+ handleDumpService((DumpComponentInfo)msg.obj);
break;
case LOW_MEMORY:
handleLowMemory();
@@ -1055,6 +1080,9 @@
case DUMP_HEAP:
handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
break;
+ case DUMP_ACTIVITY:
+ handleDumpActivity((DumpComponentInfo)msg.obj);
+ break;
}
}
@@ -2020,9 +2048,9 @@
}
}
- private void handleDumpService(DumpServiceInfo info) {
+ private void handleDumpService(DumpComponentInfo info) {
try {
- Service s = mServices.get(info.service);
+ Service s = mServices.get(info.token);
if (s != null) {
PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
s.dump(info.fd, pw, info.args);
@@ -2036,6 +2064,22 @@
}
}
+ private void handleDumpActivity(DumpComponentInfo info) {
+ try {
+ ActivityClientRecord r = mActivities.get(info.token);
+ if (r != null && r.activity != null) {
+ PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
+ r.activity.dump(info.fd, pw, info.args);
+ pw.close();
+ }
+ } finally {
+ synchronized (info) {
+ info.dumped = true;
+ info.notifyAll();
+ }
+ }
+ }
+
private final void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index dc2145f..95689fc 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -414,6 +414,21 @@
dumpHeap(managed, path, fd);
return true;
}
+
+ case DUMP_ACTIVITY_TRANSACTION: {
+ data.enforceInterface(IApplicationThread.descriptor);
+ ParcelFileDescriptor fd = data.readFileDescriptor();
+ final IBinder activity = data.readStrongBinder();
+ final String[] args = data.readStringArray();
+ if (fd != null) {
+ dumpActivity(fd.getFileDescriptor(), activity, args);
+ try {
+ fd.close();
+ } catch (IOException e) {
+ }
+ }
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -857,5 +872,16 @@
IBinder.FLAG_ONEWAY);
data.recycle();
}
+
+ public void dumpActivity(FileDescriptor fd, IBinder token, String[] args)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeFileDescriptor(fd);
+ data.writeStrongBinder(token);
+ data.writeStringArray(args);
+ mRemote.transact(DUMP_ACTIVITY_TRANSACTION, data, null, 0);
+ data.recycle();
+ }
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 1cbed79..12bf7e5 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -38,6 +38,8 @@
import android.view.View.OnCreateContextMenuListener;
import android.widget.AdapterView;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.HashMap;
final class FragmentState implements Parcelable {
@@ -207,7 +209,7 @@
*
* <p>An activity's layout XML can include <code><fragment></code> tags
* to embed fragment instances inside of the layout. For example, here is
- * a simply layout that embeds one fragment:</p>
+ * a simple layout that embeds one fragment:</p>
*
* {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
*
@@ -251,6 +253,33 @@
* details activity will finish of it finds itself running in a configuration
* where the details can be shown inline.
*
+ * <p>When a configuration change causes the activity hosting these fragments
+ * to restart, its new instance may use a different layout that doesn't
+ * include the same fragments as the previous layout. In this case all of
+ * the previous fragments will still be instantiated and running in the new
+ * instance; however, any that are no longer associated with a <fragment>
+ * tag in the view hierarchy will not have their content view created and will
+ * return false from {@link #isInLayout}.
+ *
+ * <p>The attributes of the <fragment> tag are used to control the
+ * LayoutParams provider when attaching the fragment's view to the parent
+ * container. They can alse be parsed by the fragment in {@link #onInflate}
+ * as parameters.
+ *
+ * <p>The fragment being instantiated must have some kind of unique identifier
+ * so that it can be re-associated with a previous instance if the parent
+ * activity needs to be destroyed and recreated. This can be provided these
+ * ways:
+ *
+ * <ul>
+ * <li>If nothing is explicitly supplied, the view ID of the container will
+ * be used.
+ * <li><code>android:tag</code> can be used in <fragment> to provide
+ * a specific tag name for the fragment.
+ * <li><code>android:id</code> can be used in <fragment> to provide
+ * a specific identifier for the fragment.
+ * </ul>
+ *
* <a name="BackStack"></a>
* <h3>Back Stack</h3>
*
@@ -316,6 +345,9 @@
// Set to true if this fragment was instantiated from a layout file.
boolean mFromLayout;
+ // Set to true when the view has actually been inflated in its layout.
+ boolean mInLayout;
+
// Number of active back stack entries this fragment is in.
int mBackStackNesting;
@@ -585,7 +617,7 @@
/**
* Return the FragmentManager for interacting with fragments associated
* with this fragment's activity. Note that this will be non-null slightly
- * before {@link #getActivity()}, in the time from when the fragment is
+ * before {@link #getActivity()}, during the time from when the fragment is
* placed in a {@link FragmentTransaction} until it is committed and
* attached to its activity.
*/
@@ -601,6 +633,17 @@
}
/**
+ * Return true if the layout is included as part of an activity view
+ * hierarchy via the <fragment> tag. This will always be true when
+ * fragments are created through the <fragment> tag, <em>except</em>
+ * in the case where an old fragment is restored from a previous state and
+ * it does not appear in the layout of the current state.
+ */
+ final public boolean isInLayout() {
+ return mInLayout;
+ }
+
+ /**
* Return true if the fragment is in the resumed state. This is true
* for the duration of {@link #onResume()} and {@link #onPause()} as well.
*/
@@ -1075,6 +1118,76 @@
return false;
}
+ /**
+ * Print the Fragments's state into the given stream.
+ *
+ * @param prefix Text to print at the front of each line.
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer The PrintWriter to which you should dump your state. This will be
+ * closed for you after you return.
+ * @param args additional arguments to the dump request.
+ */
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.print(prefix); writer.print("mFragmentId="); writer.print(mFragmentId);
+ writer.print(" mContainerId="); writer.print(mContainerId);
+ writer.print(" mTag="); writer.println(mTag);
+ writer.print(prefix); writer.print("mState="); writer.print(mState);
+ writer.print(" mIndex="); writer.print(mIndex);
+ writer.print(" mWho="); writer.print(mWho);
+ writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
+ writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
+ writer.print(" mResumed="); writer.print(mResumed);
+ writer.print(" mFromLayout="); writer.print(mFromLayout);
+ writer.print(" mInLayout="); writer.println(mInLayout);
+ writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
+ writer.print(" mRetainInstance="); writer.print(mRetainInstance);
+ writer.print(" mRetaining="); writer.print(mRetaining);
+ writer.print(" mHasMenu="); writer.println(mHasMenu);
+ if (mFragmentManager != null) {
+ writer.print(prefix); writer.print("mFragmentManager=");
+ writer.println(mFragmentManager);
+ }
+ if (mImmediateActivity != null) {
+ writer.print(prefix); writer.print("mImmediateActivity=");
+ writer.println(mImmediateActivity);
+ }
+ if (mActivity != null) {
+ writer.print(prefix); writer.print("mActivity=");
+ writer.println(mActivity);
+ }
+ if (mArguments != null) {
+ writer.print(prefix); writer.print("mArguments="); writer.println(mArguments);
+ }
+ if (mSavedFragmentState != null) {
+ writer.print(prefix); writer.print("mSavedFragmentState=");
+ writer.println(mSavedFragmentState);
+ }
+ if (mSavedViewState != null) {
+ writer.print(prefix); writer.print("mSavedViewState=");
+ writer.println(mSavedViewState);
+ }
+ if (mTarget != null) {
+ writer.print(prefix); writer.print("mTarget="); writer.print(mTarget);
+ writer.print(" mTargetRequestCode=");
+ writer.println(mTargetRequestCode);
+ }
+ if (mNextAnim != 0) {
+ writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim);
+ }
+ if (mContainer != null) {
+ writer.print(prefix); writer.print("mContainer="); writer.println(mContainer);
+ }
+ if (mView != null) {
+ writer.print(prefix); writer.print("mView="); writer.println(mView);
+ }
+ if (mLoaderManager != null) {
+ writer.print(prefix); writer.print("mLoaderManager="); writer.print(mLoaderManager);
+ writer.print(" mStarted="); writer.print(mStarted);
+ writer.print(" mCheckedForLoaderManager=");
+ writer.println(mCheckedForLoaderManager);
+ }
+ }
+
void performStop() {
onStop();
if (mStarted) {
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java
index 0d39d0b..22e0747 100644
--- a/core/java/android/app/FragmentBreadCrumbs.java
+++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -16,6 +16,7 @@
package android.app;
+import android.app.FragmentManager.BackStackEntry;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -139,14 +140,14 @@
FragmentManager fm = mActivity.getFragmentManager();
int numEntries = fm.countBackStackEntries();
int numViews = mContainer.getChildCount();
- for (int i=mTopEntry != null ? -1 : 0; i<numEntries; i++) {
- FragmentManager.BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
- int viewI = mTopEntry != null ? i+1 : i;
+ for (int i = mTopEntry != null ? -1 : 0; i < numEntries; i++) {
+ BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
+ int viewI = mTopEntry != null ? i + 1 : i;
if (viewI < numViews) {
View v = mContainer.getChildAt(viewI);
Object tag = v.getTag();
if (tag != bse) {
- for (int j=viewI; j<numViews; j++) {
+ for (int j = viewI; j < numViews; j++) {
mContainer.removeViewAt(viewI);
}
numViews = viewI;
@@ -163,13 +164,24 @@
text.setCompoundDrawables(null, null, null, null);
}
mContainer.addView(item);
+ item.setOnClickListener(mOnClickListener);
}
}
- int viewI = mTopEntry != null ? numEntries+1 : numEntries;
+ int viewI = mTopEntry != null ? numEntries + 1 : numEntries;
numViews = mContainer.getChildCount();
while (numViews > viewI) {
mContainer.removeViewAt(numViews-1);
numViews--;
}
}
+
+ private OnClickListener mOnClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (v.getTag() instanceof BackStackEntry) {
+ BackStackEntry bse = (BackStackEntry) v.getTag();
+ mActivity.getFragmentManager().popBackStack(bse.getId(),
+ bse == mTopEntry? FragmentManager.POP_BACK_STACK_INCLUSIVE : 0);
+ }
+ }
+ };
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 9f958246..da7ba6f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -32,6 +32,8 @@
import android.view.View;
import android.view.ViewGroup;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
/**
@@ -190,6 +192,16 @@
* the given reference.
*/
public Fragment getFragment(Bundle bundle, String key);
+
+ /**
+ * Print the FragmentManager's state into the given stream.
+ *
+ * @param prefix Text to print at the front of each line.
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer A PrintWriter to which the dump is to be set.
+ * @param args additional arguments to the dump request.
+ */
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
}
final class FragmentManagerState implements Parcelable {
@@ -270,18 +282,23 @@
execPendingActions();
}
};
+
+ @Override
public FragmentTransaction openTransaction() {
return new BackStackRecord(this);
}
+ @Override
public boolean popBackStack() {
return popBackStackState(mActivity.mHandler, null, -1, 0);
}
+ @Override
public boolean popBackStack(String name, int flags) {
return popBackStackState(mActivity.mHandler, name, -1, flags);
}
+ @Override
public boolean popBackStack(int id, int flags) {
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
@@ -289,14 +306,17 @@
return popBackStackState(mActivity.mHandler, null, id, flags);
}
+ @Override
public int countBackStackEntries() {
return mBackStack != null ? mBackStack.size() : 0;
}
+ @Override
public BackStackEntry getBackStackEntry(int index) {
return mBackStack.get(index);
}
+ @Override
public void addOnBackStackChangedListener(OnBackStackChangedListener listener) {
if (mBackStackChangeListeners == null) {
mBackStackChangeListeners = new ArrayList<OnBackStackChangedListener>();
@@ -304,12 +324,14 @@
mBackStackChangeListeners.add(listener);
}
+ @Override
public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) {
if (mBackStackChangeListeners != null) {
mBackStackChangeListeners.remove(listener);
}
}
+ @Override
public void putFragment(Bundle bundle, String key, Fragment fragment) {
if (fragment.mIndex < 0) {
throw new IllegalStateException("Fragment " + fragment
@@ -318,6 +340,7 @@
bundle.putInt(key, fragment.mIndex);
}
+ @Override
public Fragment getFragment(Bundle bundle, String key) {
int index = bundle.getInt(key, -1);
if (index == -1) {
@@ -335,6 +358,51 @@
return f;
}
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ if (mActive == null || mActive.size() <= 0) {
+ return;
+ }
+
+ writer.print(prefix); writer.println("Active Fragments:");
+
+ String innerPrefix = prefix + " ";
+
+ int N = mActive.size();
+ for (int i=0; i<N; i++) {
+ Fragment f = mActive.get(i);
+ if (f != null) {
+ writer.print(prefix); writer.print(" #"); writer.print(i);
+ writer.print(": "); writer.println(f.toString());
+ f.dump(innerPrefix, fd, writer, args);
+ }
+ }
+
+ if (mAdded != null) {
+ N = mAdded.size();
+ if (N > 0) {
+ writer.print(prefix); writer.println("Added Fragments:");
+ for (int i=0; i<N; i++) {
+ Fragment f = mAdded.get(i);
+ writer.print(prefix); writer.print(" #"); writer.print(i);
+ writer.print(": "); writer.println(f.toString());
+ }
+ }
+ }
+
+ if (mBackStack != null) {
+ N = mBackStack.size();
+ if (N > 0) {
+ writer.print(prefix); writer.println("Back Stack:");
+ for (int i=0; i<N; i++) {
+ BackStackRecord bs = mBackStack.get(i);
+ writer.print(prefix); writer.print(" #"); writer.print(i);
+ writer.print(": "); writer.println(bs.toString());
+ }
+ }
+ }
+ }
+
Animator loadAnimator(Fragment fragment, int transit, boolean enter,
int transitionStyle) {
Animator animObj = fragment.onCreateAnimator(transit, enter,
@@ -436,7 +504,7 @@
if (f.mContainerId != 0) {
container = (ViewGroup)mActivity.findViewById(f.mContainerId);
if (container == null) {
- throw new IllegalArgumentException("New view found for id 0x"
+ throw new IllegalArgumentException("No view found for id 0x"
+ Integer.toHexString(f.mContainerId)
+ " for fragment " + f);
}
@@ -519,7 +587,7 @@
if (f.mView != null) {
// Need to save the current view state if not
// done already.
- if (!mActivity.isFinishing() && f.mSavedFragmentState == null) {
+ if (!mActivity.isFinishing() && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
@@ -581,6 +649,10 @@
f.mState = newState;
}
+ void moveToState(Fragment f) {
+ moveToState(f, mCurState, 0, 0);
+ }
+
void moveToState(int newState, boolean always) {
moveToState(newState, 0, 0, always);
}
@@ -655,7 +727,7 @@
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
- moveToState(fragment, mCurState, 0, 0);
+ moveToState(fragment);
}
}
@@ -1010,37 +1082,42 @@
FragmentState fs = new FragmentState(f);
active[i] = fs;
- if (mStateBundle == null) {
- mStateBundle = new Bundle();
- }
- f.onSaveInstanceState(mStateBundle);
- if (!mStateBundle.isEmpty()) {
- fs.mSavedFragmentState = mStateBundle;
- mStateBundle = null;
- }
-
- if (f.mView != null) {
- saveFragmentViewState(f);
- if (f.mSavedViewState != null) {
+ if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
+ if (mStateBundle == null) {
+ mStateBundle = new Bundle();
+ }
+ f.onSaveInstanceState(mStateBundle);
+ if (!mStateBundle.isEmpty()) {
+ fs.mSavedFragmentState = mStateBundle;
+ mStateBundle = null;
+ }
+
+ if (f.mView != null) {
+ saveFragmentViewState(f);
+ if (f.mSavedViewState != null) {
+ if (fs.mSavedFragmentState == null) {
+ fs.mSavedFragmentState = new Bundle();
+ }
+ fs.mSavedFragmentState.putSparseParcelableArray(
+ FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
+ }
+ }
+
+ if (f.mTarget != null) {
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
- fs.mSavedFragmentState.putSparseParcelableArray(
- FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
+ putFragment(fs.mSavedFragmentState,
+ FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
+ if (f.mTargetRequestCode != 0) {
+ fs.mSavedFragmentState.putInt(
+ FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
+ f.mTargetRequestCode);
+ }
}
- }
- if (f.mTarget != null) {
- if (fs.mSavedFragmentState == null) {
- fs.mSavedFragmentState = new Bundle();
- }
- putFragment(fs.mSavedFragmentState,
- FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
- if (f.mTargetRequestCode != 0) {
- fs.mSavedFragmentState.putInt(
- FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
- f.mTargetRequestCode);
- }
+ } else {
+ fs.mSavedFragmentState = f.mSavedFragmentState;
}
if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
@@ -1057,13 +1134,15 @@
BackStackState[] backStack = null;
// Build list of currently added fragments.
- N = mAdded.size();
- if (N > 0) {
- added = new int[N];
- for (int i=0; i<N; i++) {
- added[i] = mAdded.get(i).mIndex;
- if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
- + ": " + mAdded.get(i));
+ if (mAdded != null) {
+ N = mAdded.size();
+ if (N > 0) {
+ added = new int[N];
+ for (int i=0; i<N; i++) {
+ added[i] = mAdded.get(i).mIndex;
+ if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
+ + ": " + mAdded.get(i));
+ }
}
}
@@ -1104,6 +1183,7 @@
fs.mInstance = f;
f.mSavedViewState = null;
f.mBackStackNesting = 0;
+ f.mInLayout = false;
f.mAdded = false;
if (fs.mSavedFragmentState != null) {
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 039bcb9..1f8a7c58 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -105,7 +105,9 @@
static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
void scheduleCrash(String msg) throws RemoteException;
-
+ void dumpActivity(FileDescriptor fd, IBinder servicetoken, String[] args)
+ throws RemoteException;
+
String descriptor = "android.app.IApplicationThread";
int SCHEDULE_PAUSE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
@@ -143,4 +145,5 @@
int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
int SCHEDULE_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
+ int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
}
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index 1081609..fc5ebb3 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -365,7 +365,6 @@
*
* @param show whether the download manager should show a notification for this download.
* @return this object
- * @hide
*/
public Request setShowRunningNotification(boolean show) {
mShowNotification = show;
diff --git a/core/java/android/net/LinkCapabilities.aidl b/core/java/android/net/LinkCapabilities.aidl
index 5f47baf..df72599 100644
--- a/core/java/android/net/LinkCapabilities.aidl
+++ b/core/java/android/net/LinkCapabilities.aidl
@@ -1,7 +1,6 @@
/*
**
-** Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
-** Copyright (C) 2009 The Android Open Source Project
+** 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.
diff --git a/core/java/android/net/LinkCapabilities.java b/core/java/android/net/LinkCapabilities.java
index d10a759..eb9166f 100644
--- a/core/java/android/net/LinkCapabilities.java
+++ b/core/java/android/net/LinkCapabilities.java
@@ -146,7 +146,7 @@
// code these to match
/** Default Role */
- public static final String DEFAULT = "0";
+ public static final String DEFAULT = "default";
/** Bulk down load */
public static final String BULK_DOWNLOAD = "bulk.download";
/** Bulk upload */
diff --git a/core/java/android/net/LinkProperties.aidl b/core/java/android/net/LinkProperties.aidl
index 73c7988..9cd06d5 100644
--- a/core/java/android/net/LinkProperties.aidl
+++ b/core/java/android/net/LinkProperties.aidl
@@ -1,7 +1,6 @@
/*
**
-** Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
-** Copyright (C) 2009 The Android Open Source Project
+** 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.
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 24aebfc..f411eac 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * 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.
diff --git a/core/java/android/net/LinkSocket.java b/core/java/android/net/LinkSocket.java
index d416ed0..5aa6451 100644
--- a/core/java/android/net/LinkSocket.java
+++ b/core/java/android/net/LinkSocket.java
@@ -197,6 +197,17 @@
/**
* Connect a duplicate socket socket to the same remote host address and port
+ * as the original with a timeout parameter.
+ * @param timeout the timeout value in milliseconds or 0 for infinite timeout
+ * @throws IOException if the socket is already connected or an error occurs
+ * while connecting
+ */
+ public void connect(int timeout) throws IOException {
+ if (DBG) log("connect(timeout) EX");
+ }
+
+ /**
+ * Connect a duplicate socket socket to the same remote host address and port
* as the original.
* @throws IOException if the socket is already connected or an error occurs
* while connecting
@@ -237,9 +248,9 @@
*/
@Override
@Deprecated
- public void bind(SocketAddress localAddr) throws IOException {
+ public void bind(SocketAddress localAddr) throws UnsupportedOperationException {
if (DBG) log("bind(localAddr) EX throws IOException");
- throw new IOException("bind is deprecated for LinkSocket");
+ throw new UnsupportedOperationException("bind is deprecated for LinkSocket");
}
/**
diff --git a/core/java/android/net/LinkSocketNotifier.java b/core/java/android/net/LinkSocketNotifier.java
index 183c767..28e2834 100644
--- a/core/java/android/net/LinkSocketNotifier.java
+++ b/core/java/android/net/LinkSocketNotifier.java
@@ -84,5 +84,5 @@
* Get notified of every capability change
* check for LinkSockets on that Link that are interested in that Capability - call them
*/
- public void onCapabilityChanged(LinkSocket socket, LinkCapabilities changedCapabilities);
+ public void onCapabilitiesChanged(LinkSocket socket, LinkCapabilities changedCapabilities);
}
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index fb59fed..140b71f 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * 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.
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index e89f7c2..be5b685 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -33,6 +33,7 @@
public class MessageQueue {
Message mMessages;
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
+ private IdleHandler[] mPendingIdleHandlers;
private boolean mQuiting = false;
boolean mQuitAllowed = true;
@@ -105,91 +106,75 @@
}
final Message next() {
- boolean tryIdle = true;
- // when we start out, we'll just touch the input pipes and then go from there
- int timeToNextEventMillis = 0;
+ int pendingIdleHandlerCount = -1; // -1 only during first iteration
+ int nextPollTimeoutMillis = 0;
- while (true) {
- long now;
- Object[] idlers = null;
+ for (;;) {
+ if (nextPollTimeoutMillis != 0) {
+ Binder.flushPendingCommands();
+ }
+ nativePollOnce(nextPollTimeoutMillis);
- boolean dispatched = nativePollOnce(timeToNextEventMillis);
-
- // Try to retrieve the next message, returning if found.
synchronized (this) {
- now = SystemClock.uptimeMillis();
- Message msg = pullNextLocked(now);
+ // Try to retrieve the next message. Return if found.
+ final long now = SystemClock.uptimeMillis();
+ final Message msg = mMessages;
if (msg != null) {
- msg.markInUse();
- return msg;
- }
-
- if (tryIdle && mIdleHandlers.size() > 0) {
- idlers = mIdleHandlers.toArray();
- }
- }
-
- // There was no message so we are going to wait... but first,
- // if there are any idle handlers let them know.
- boolean didIdle = false;
- if (idlers != null) {
- for (Object idler : idlers) {
- boolean keep = false;
- try {
- didIdle = true;
- keep = ((IdleHandler)idler).queueIdle();
- } catch (Throwable t) {
- Log.wtf("MessageQueue", "IdleHandler threw exception", t);
- }
-
- if (!keep) {
- synchronized (this) {
- mIdleHandlers.remove(idler);
- }
- }
- }
- }
-
- // While calling an idle handler, a new message could have been
- // delivered... so go back and look again for a pending message.
- if (didIdle) {
- tryIdle = false;
- continue;
- }
-
- synchronized (this) {
- // No messages, nobody to tell about it... time to wait!
- if (mMessages != null) {
- long longTimeToNextEventMillis = mMessages.when - now;
-
- if (longTimeToNextEventMillis > 0) {
- Binder.flushPendingCommands();
- timeToNextEventMillis = (int) Math.min(longTimeToNextEventMillis,
- Integer.MAX_VALUE);
+ final long when = msg.when;
+ if (now >= when) {
+ mMessages = msg.next;
+ if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
+ msg.markInUse();
+ return msg;
} else {
- timeToNextEventMillis = 0;
+ nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
}
} else {
- Binder.flushPendingCommands();
- timeToNextEventMillis = -1;
+ nextPollTimeoutMillis = -1;
+ }
+
+ // If first time, then get the number of idlers to run.
+ if (pendingIdleHandlerCount < 0) {
+ pendingIdleHandlerCount = mIdleHandlers.size();
+ }
+ if (pendingIdleHandlerCount == 0) {
+ // No idle handlers to run. Loop and wait some more.
+ continue;
+ }
+
+ if (mPendingIdleHandlers == null) {
+ mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
+ }
+ mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
+ }
+
+ // Run the idle handlers.
+ // We only ever reach this code block during the first iteration.
+ for (int i = 0; i < pendingIdleHandlerCount; i++) {
+ final IdleHandler idler = mPendingIdleHandlers[i];
+ mPendingIdleHandlers[i] = null; // release the reference to the handler
+
+ boolean keep = false;
+ try {
+ keep = idler.queueIdle();
+ } catch (Throwable t) {
+ Log.wtf("MessageQueue", "IdleHandler threw exception", t);
+ }
+
+ if (!keep) {
+ synchronized (this) {
+ mIdleHandlers.remove(idler);
+ }
}
}
- // loop to the while(true) and do the appropriate nativeWait(when)
- }
- }
- final Message pullNextLocked(long now) {
- Message msg = mMessages;
- if (msg != null) {
- if (now >= msg.when) {
- mMessages = msg.next;
- if (Config.LOGV) Log.v(
- "MessageQueue", "Returning message: " + msg);
- return msg;
- }
- }
+ // Reset the idle handler count to 0 so we do not run them again.
+ pendingIdleHandlerCount = 0;
- return null;
+ // While calling an idle handler, a new message could have been delivered
+ // so go back and look again for a pending message without waiting.
+ nextPollTimeoutMillis = 0;
+ }
}
final boolean enqueueMessage(Message msg, long when) {
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 5fea6fe..e56e257 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -307,8 +307,10 @@
* Requires the {@link android.Manifest.permission#REBOOT} permission.
*
* @param context the Context to use
- * @param packageFile the update package to install. Currently
- * must be on the /cache or /data partitions.
+ * @param packageFile the update package to install. Must be on
+ * a partition mountable by recovery. (The set of partitions
+ * known to recovery may vary from device to device. Generally,
+ * /cache and /data are safe.)
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
@@ -316,15 +318,6 @@
public static void installPackage(Context context, File packageFile)
throws IOException {
String filename = packageFile.getCanonicalPath();
-
- if (filename.startsWith("/cache/")) {
- filename = "CACHE:" + filename.substring(7);
- } else if (filename.startsWith("/data/")) {
- filename = "DATA:" + filename.substring(6);
- } else {
- throw new IllegalArgumentException(
- "Must start with /cache or /data: " + filename);
- }
Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
String arg = "--update_package=" + filename;
bootCommand(context, arg);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4d87b79..51dc6ae 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1494,6 +1494,12 @@
public static final String AUTO_TIME = "auto_time";
/**
+ * Value to specify if the user prefers the time zone
+ * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+ */
+ public static final String AUTO_TIME_ZONE = "auto_time_zone";
+
+ /**
* Display times as 12 or 24 hours
* 12
* 24
@@ -1775,6 +1781,7 @@
TEXT_AUTO_PUNCTUATE,
TEXT_SHOW_PASSWORD,
AUTO_TIME,
+ AUTO_TIME_ZONE,
TIME_12_24,
DATE_FORMAT,
ACCELEROMETER_ROTATION,
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 0408673..733b535 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -314,6 +314,8 @@
* {@link MotionEvent#ACTION_CANCEL} event), the controller is reset to null.
*
* @param cursorController A cursor controller implementation
+ *
+ * @hide
*/
public void setCursorController(CursorController cursorController) {
mCursorController = cursorController;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 458274f..d24af52 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -67,6 +67,7 @@
// these are optional, set by the caller
private boolean mFactorySet;
private Factory mFactory;
+ private Factory2 mFactory2;
private Filter mFilter;
private final Object[] mConstructorArgs = new Object[2];
@@ -122,12 +123,33 @@
public View onCreateView(String name, Context context, AttributeSet attrs);
}
- private static class FactoryMerger implements Factory {
+ public interface Factory2 extends Factory {
+ /**
+ * Version of {@link #onCreateView(String, Context, AttributeSet)}
+ * that also supplies the parent that the view created view will be
+ * placed in.
+ *
+ * @param parent The parent that the created view will be placed
+ * in; <em>note that this may be null</em>.
+ * @param name Tag name to be inflated.
+ * @param context The context the view is being created in.
+ * @param attrs Inflation attributes as specified in XML file.
+ *
+ * @return View Newly created view. Return null for the default
+ * behavior.
+ */
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
+ }
+
+ private static class FactoryMerger implements Factory2 {
private final Factory mF1, mF2;
+ private final Factory2 mF12, mF22;
- FactoryMerger(Factory f1, Factory f2) {
+ FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
mF1 = f1;
mF2 = f2;
+ mF12 = f12;
+ mF22 = f22;
}
public View onCreateView(String name, Context context, AttributeSet attrs) {
@@ -135,6 +157,14 @@
if (v != null) return v;
return mF2.onCreateView(name, context, attrs);
}
+
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
+ : mF1.onCreateView(name, context, attrs);
+ if (v != null) return v;
+ return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
+ : mF2.onCreateView(name, context, attrs);
+ }
}
/**
@@ -162,6 +192,7 @@
protected LayoutInflater(LayoutInflater original, Context newContext) {
mContext = newContext;
mFactory = original.mFactory;
+ mFactory2 = original.mFactory2;
mFilter = original.mFilter;
}
@@ -200,7 +231,7 @@
}
/**
- * Return the current factory (or null). This is called on each element
+ * Return the current {@link Factory} (or null). This is called on each element
* name. If the factory returns a View, add that to the hierarchy. If it
* returns null, proceed to call onCreateView(name).
*/
@@ -209,6 +240,17 @@
}
/**
+ * Return the current {@link Factory2}. Returns null if no factory is set
+ * or the set factory does not implement the {@link Factory2} interface.
+ * This is called on each element
+ * name. If the factory returns a View, add that to the hierarchy. If it
+ * returns null, proceed to call onCreateView(name).
+ */
+ public final Factory2 getFactory2() {
+ return mFactory2;
+ }
+
+ /**
* Attach a custom Factory interface for creating views while using
* this LayoutInflater. This must not be null, and can only be set once;
* after setting, you can not change the factory. This is
@@ -234,7 +276,26 @@
if (mFactory == null) {
mFactory = factory;
} else {
- mFactory = new FactoryMerger(factory, mFactory);
+ mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
+ }
+ }
+
+ /**
+ * Like {@link #setFactory}, but allows you to set a {@link Factory2}
+ * interface.
+ */
+ public void setFactory2(Factory2 factory) {
+ if (mFactorySet) {
+ throw new IllegalStateException("A factory has already been set on this LayoutInflater");
+ }
+ if (factory == null) {
+ throw new NullPointerException("Given factory can not be null");
+ }
+ mFactorySet = true;
+ if (mFactory == null) {
+ mFactory = mFactory2 = factory;
+ } else {
+ mFactory = new FactoryMerger(factory, factory, mFactory, mFactory2);
}
}
@@ -384,7 +445,7 @@
rInflate(parser, root, attrs, false);
} else {
// Temp is the root view that was found in the xml
- View temp = createViewFromTag(name, attrs);
+ View temp = createViewFromTag(root, name, attrs);
ViewGroup.LayoutParams params = null;
@@ -557,10 +618,27 @@
return createView(name, "android.view.", attrs);
}
+ /**
+ * Version of {@link #onCreateView(String, AttributeSet)} that also
+ * takes the future parent of the view being constructure. The default
+ * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
+ *
+ * @param parent The future parent of the returned view. <em>Note that
+ * this may be null.</em>
+ * @param name The fully qualified class name of the View to be create.
+ * @param attrs An AttributeSet of attributes to apply to the View.
+ *
+ * @return View The View created.
+ */
+ protected View onCreateView(View parent, String name, AttributeSet attrs)
+ throws ClassNotFoundException {
+ return onCreateView(name, attrs);
+ }
+
/*
* default visibility so the BridgeInflater can override it.
*/
- View createViewFromTag(String name, AttributeSet attrs) {
+ View createViewFromTag(View parent, String name, AttributeSet attrs) {
if (name.equals("view")) {
name = attrs.getAttributeValue(null, "class");
}
@@ -568,12 +646,14 @@
if (DEBUG) System.out.println("******** Creating view: " + name);
try {
- View view = (mFactory == null) ? null : mFactory.onCreateView(name,
- mContext, attrs);
+ View view;
+ if (mFactory2 != null) view = mFactory2.onCreateView(parent, name, mContext, attrs);
+ else if (mFactory != null) view = mFactory.onCreateView(name, mContext, attrs);
+ else view = null;
if (view == null) {
if (-1 == name.indexOf('.')) {
- view = onCreateView(name, attrs);
+ view = onCreateView(parent, name, attrs);
} else {
view = createView(name, null, attrs);
}
@@ -628,7 +708,7 @@
} else if (TAG_MERGE.equals(name)) {
throw new InflateException("<merge /> must be the root element");
} else {
- final View view = createViewFromTag(name, attrs);
+ final View view = createViewFromTag(parent, name, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
rInflate(parser, view, attrs, true);
@@ -689,7 +769,7 @@
// Inflate all children.
rInflate(childParser, parent, childAttrs, false);
} else {
- final View view = createViewFromTag(childName, childAttrs);
+ final View view = createViewFromTag(parent, childName, childAttrs);
final ViewGroup group = (ViewGroup) parent;
// We try to load the layout params set in the <include /> tag. If
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 97d58d2..3d5aff7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1613,12 +1613,6 @@
private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
/**
- * Indicates that this view has a visible/touchable overlay.
- * @hide
- */
- static final int HAS_OVERLAY = 0x10000000;
-
- /**
* Indicates that pivotX or pivotY were explicitly set and we should not assume the center
* for transform operations
*
@@ -3040,57 +3034,6 @@
resetPressedState();
}
- /**
- * Enable or disable drawing overlays after a full drawing pass. This enables a view to
- * draw on a topmost overlay layer after normal drawing completes and get right of first
- * refusal for touch events in the window.
- *
- * <em>Warning:</em> Views that use this feature should take care to disable/enable overlay
- * appropriately when they are attached/detached from their window. All overlays should be
- * disabled when detached.
- *
- * @param enabled true if overlay drawing should be enabled for this view, false otherwise
- *
- * @see #onDrawOverlay(Canvas)
- *
- * @hide
- */
- protected void setOverlayEnabled(boolean enabled) {
- final boolean oldValue = (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
- mPrivateFlags = (mPrivateFlags & ~HAS_OVERLAY) | (enabled ? HAS_OVERLAY : 0);
- if (enabled != oldValue) {
- final ViewParent parent = getParent();
- if (parent != null) {
- try {
- parent.childOverlayStateChanged(this);
- } catch (AbstractMethodError e) {
- Log.e(VIEW_LOG_TAG, "Could not propagate hasOverlay state", e);
- }
- }
- }
- }
-
- /**
- * @return true if this View has an overlay enabled.
- *
- * @see #setOverlayEnabled(boolean)
- * @see #onDrawOverlay(Canvas)
- *
- * @hide
- */
- public boolean isOverlayEnabled() {
- return (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
- }
-
- /**
- * Override this method to draw on an overlay layer above all other views in the window
- * after the standard drawing pass is complete. This allows a view to draw outside its
- * normal boundaries.
- * @hide
- */
- public void onDrawOverlay(Canvas canvas) {
- }
-
private void resetPressedState() {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3db4857..2b92e872 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -245,11 +245,6 @@
protected static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
/**
- * When set, at least one child of this ViewGroup will return true from hasOverlay.
- */
- private static final int FLAG_CHILD_HAS_OVERLAY = 0x100000;
-
- /**
* When set, this ViewGroup will split MotionEvents to multiple child Views when appropriate.
*/
private static final int FLAG_SPLIT_MOTION_EVENTS = 0x200000;
@@ -910,33 +905,6 @@
final View[] children = mChildren;
final int count = mChildrenCount;
- // Check for children with overlays first. They don't rely on hit rects to determine
- // if they can accept a new touch event.
- if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
- for (int i = count - 1; i >= 0; i--) {
- final View child = children[i];
- // Don't let children respond to events as an overlay during an animation.
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
- && child.getAnimation() == null
- && child.isOverlayEnabled()) {
- // offset the event to the view's coordinate system
- final float xc = scrolledXFloat - child.mLeft;
- final float yc = scrolledYFloat - child.mTop;
- ev.setLocation(xc, yc);
- child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
- if (child.dispatchTouchEvent(ev)) {
- // Event handled, we have a target now.
- mMotionTarget = child;
- return true;
- }
- // The event didn't get handled, try the next view.
- // Don't reset the event's location, it's not
- // necessary here.
- }
- }
- }
-
- // Now check views normally.
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
@@ -2774,8 +2742,6 @@
if (clearChildFocus != null) {
clearChildFocus(clearChildFocus);
}
-
- mGroupFlags &= ~FLAG_CHILD_HAS_OVERLAY;
}
/**
@@ -3024,8 +2990,7 @@
final int left = mLeft;
final int top = mTop;
- if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY ||
- dirty.intersect(0, 0, mRight - left, mBottom - top) ||
+ if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
(mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
@@ -4013,69 +3978,6 @@
}
/**
- * Called when a child's overlay state changes between enabled/disabled.
- * @param child Child view whose state has changed or null
- * @hide
- */
- public void childOverlayStateChanged(View child) {
- boolean childHasOverlay = false;
- if (child != null) {
- childHasOverlay = child.isOverlayEnabled();
- } else {
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- if (childHasOverlay |= getChildAt(i).isOverlayEnabled()) {
- break;
- }
- }
- }
-
- final boolean hasChildWithOverlay = childHasOverlay ||
- (mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY;
-
- final boolean oldValue = isOverlayEnabled();
- mGroupFlags = (mGroupFlags & ~FLAG_CHILD_HAS_OVERLAY) |
- (hasChildWithOverlay ? FLAG_CHILD_HAS_OVERLAY : 0);
- if (isOverlayEnabled() != oldValue) {
- final ViewParent parent = getParent();
- if (parent != null) {
- try {
- parent.childOverlayStateChanged(this);
- } catch (AbstractMethodError e) {
- Log.e("ViewGroup", "Could not propagate hasOverlay state", e);
- }
- }
- }
- }
-
- /**
- * @hide
- */
- public boolean isOverlayEnabled() {
- return super.isOverlayEnabled() ||
- ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY);
- }
-
- /**
- * @hide
- */
- @Override
- public void onDrawOverlay(Canvas canvas) {
- if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- final View child = getChildAt(i);
- if (child.isOverlayEnabled()) {
- canvas.translate(child.mLeft - child.mScrollX, child.mTop - child.mScrollY);
- child.onDrawOverlay(canvas);
- canvas.translate(-(child.mLeft - child.mScrollX),
- -(child.mTop - child.mScrollY));
- }
- }
- }
- }
-
- /**
* LayoutParams are used by views to tell their parents how they want to be
* laid out. See
* {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d2907da..d7d4c3f 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -222,11 +222,4 @@
*/
public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
boolean immediate);
-
- /**
- * Called when a child view's overlay state changes between enabled/disabled.
- * @param child Child view whose state changed or null.
- * @hide
- */
- public void childOverlayStateChanged(View child);
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index cb9f84d..e71b5b6 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -206,8 +206,6 @@
AudioManager mAudioManager;
private final int mDensity;
-
- private boolean mHasOverlay;
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
@@ -1359,9 +1357,6 @@
canvas.setScreenDensity(scalingRequired
? DisplayMetrics.DENSITY_DEVICE : 0);
mView.draw(canvas);
- if (mHasOverlay) {
- mView.onDrawOverlay(canvas);
- }
} finally {
mAttachInfo.mIgnoreDirtyState = false;
}
@@ -2744,19 +2739,6 @@
return scrollToRectOrFocus(rectangle, immediate);
}
- /**
- * @hide
- */
- public void childOverlayStateChanged(View child) {
- final boolean oldState = mHasOverlay;
- mHasOverlay = child.isOverlayEnabled();
- // Invalidate the whole thing when we change overlay states just in case
- // something left chunks of data drawn someplace it shouldn't have.
- if (mHasOverlay != oldState) {
- child.invalidate();
- }
- }
-
class TakenSurfaceHolder extends BaseSurfaceHolder {
@Override
public boolean onAllowLockCanvas() {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 4a3e2a9..71f4f03 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -176,6 +176,7 @@
attrs, com.android.internal.R.styleable.PopupWindow, defStyleAttr, defStyleRes);
mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground);
+ mAnimationStyle = a.getResourceId(R.styleable.PopupWindow_windowAnimationStyle, -1);
// If this is a StateListDrawable, try to find and store the drawable to be
// used when the drop-down is placed above its anchor view, and the one to be
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3e5ddfc..d49b4d7f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -96,7 +96,6 @@
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewRoot;
@@ -199,6 +198,9 @@
private static final int PRIORITY = 100;
private int mCurrentAlpha = 255;
+
+ private final int[] mTempCoords = new int[2];
+
private ColorStateList mTextColor;
private int mCurTextColor;
private ColorStateList mHintTextColor;
@@ -3779,8 +3781,6 @@
showError();
mShowErrorAfterAttach = false;
}
-
- updateOverlay();
}
@Override
@@ -3798,8 +3798,6 @@
if (mError != null) {
hideError();
}
-
- setOverlayEnabled(false);
}
@Override
@@ -4169,19 +4167,6 @@
canvas.restore();
}
- /**
- * @hide
- */
- @Override
- public void onDrawOverlay(Canvas canvas) {
- if (mInsertionPointCursorController != null) {
- mInsertionPointCursorController.draw(canvas);
- }
- if (mSelectionModifierCursorController != null) {
- mSelectionModifierCursorController.draw(canvas);
- }
- }
-
@Override
public void getFocusedRect(Rect r) {
if (mLayout == null) {
@@ -6768,31 +6753,17 @@
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
- // Check to see if we're testing for our anchor overlay.
- boolean handled = false;
- final float x = event.getX();
- final float y = event.getY();
- if (x < 0 || x >= mRight - mLeft || y < 0 || y >= mBottom - mTop) {
- if (mInsertionPointCursorController != null) {
- handled |= mInsertionPointCursorController.onTouchEvent(event);
- }
- if (mSelectionModifierCursorController != null) {
- handled |= mSelectionModifierCursorController.onTouchEvent(event);
- }
-
- if (!handled) {
- return false;
- }
+ if (mInsertionPointCursorController != null) {
+ mInsertionPointCursorController.onTouchEvent(event);
+ }
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.onTouchEvent(event);
}
// Reset this state; it will be re-set if super.onTouchEvent
// causes focus to move to the view.
mTouchFocusSelected = false;
mScrolled = false;
-
- if (handled) {
- return true;
- }
}
final boolean superResult = super.onTouchEvent(event);
@@ -6808,7 +6779,6 @@
}
if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
-
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.onTouchEvent(event);
}
@@ -6822,11 +6792,22 @@
int oldSelStart = getSelectionStart();
int oldSelEnd = getSelectionEnd();
+ final int oldScrollX = mScrollX;
+ final int oldScrollY = mScrollY;
+
if (mMovement != null) {
handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
}
if (isTextEditable()) {
+ if (mScrollX != oldScrollX || mScrollY != oldScrollY) {
+ // Hide insertion anchor while scrolling. Leave selection.
+ hideInsertionPointCursorController();
+ if (mSelectionModifierCursorController != null &&
+ mSelectionModifierCursorController.isShowing()) {
+ mSelectionModifierCursorController.updatePosition();
+ }
+ }
if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -7705,22 +7686,13 @@
}
}
- private void updateOverlay() {
- boolean enableOverlay = false;
- if (mSelectionModifierCursorController != null) {
- enableOverlay |= mSelectionModifierCursorController.isShowing();
- }
- if (mInsertionPointCursorController != null) {
- enableOverlay |= mInsertionPointCursorController.isShowing();
- }
- setOverlayEnabled(enableOverlay);
- }
-
/**
* A CursorController instance can be used to control a cursor in the text.
*
* It can be passed to an {@link ArrowKeyMovementMethod} which can intercepts events
* and send them to this object instead of the cursor.
+ *
+ * @hide
*/
public interface CursorController {
/* Cursor fade-out animation duration, in milliseconds. */
@@ -7748,6 +7720,8 @@
*/
public void updatePosition(int x, int y);
+ public void updatePosition();
+
/**
* The controller and the cursor's positions can be link by a fixed offset,
* computed when the controller is touched, and then maintained as it moves
@@ -7766,154 +7740,192 @@
* @param event The touch event
*/
public boolean onTouchEvent(MotionEvent event);
-
- /**
- * Draws a visual representation of the controller on the canvas.
- *
- * Called at the end of {@link #draw(Canvas)}, in the content coordinates system.
- * @param canvas The Canvas used by this TextView.
- */
- public void draw(Canvas canvas);
}
- private class Handle {
- Drawable mDrawable;
- // Vertical extension of the touch region
- int mTopExtension, mBottomExtension;
- // Position of the virtual finger position on screen
- int mHotSpotVerticalPosition;
+ private class HandleView extends View {
+ private boolean mPositionOnTop = false;
+ private Drawable mDrawable;
+ private PopupWindow mContainer;
+ private int mPositionX;
+ private int mPositionY;
+ private CursorController mController;
+ private boolean mIsDragging;
- Handle(Drawable drawable) {
- mDrawable = drawable;
+ public HandleView(CursorController controller, Drawable handle) {
+ super(TextView.this.mContext);
+ mController = controller;
+ mDrawable = handle;
+ mContainer = new PopupWindow(TextView.this.mContext, null,
+ com.android.internal.R.attr.textSelectHandleWindowStyle);
+ }
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(mDrawable.getIntrinsicWidth(),
+ mDrawable.getIntrinsicHeight());
+ }
+
+ public void show() {
+ if (!isPositionInBounds()) {
+ hide();
+ return;
+ }
+ mContainer.setContentView(this);
+ final int[] coords = mTempCoords;
+ TextView.this.getLocationOnScreen(coords);
+ coords[0] += mPositionX;
+ coords[1] += mPositionY;
+ mContainer.showAtLocation(TextView.this, 0, coords[0], coords[1]);
+ }
+
+ public void hide() {
+ mIsDragging = false;
+ mContainer.dismiss();
+ }
+
+ public boolean isShowing() {
+ return mContainer.isShowing();
+ }
+
+ private boolean isPositionInBounds() {
+ final int extendedPaddingTop = getExtendedPaddingTop();
+ final int extendedPaddingBottom = getExtendedPaddingBottom();
+ final int compoundPaddingLeft = getCompoundPaddingLeft();
+ final int compoundPaddingRight = getCompoundPaddingRight();
+
+ final TextView hostView = TextView.this;
+ final int right = hostView.mRight;
+ final int left = hostView.mLeft;
+ final int bottom = hostView.mBottom;
+ final int top = hostView.mTop;
+
+ final int clipLeft = left + compoundPaddingLeft;
+ final int clipTop = top + extendedPaddingTop;
+ final int clipRight = right - compoundPaddingRight;
+ final int clipBottom = bottom - extendedPaddingBottom;
+
+ final int handleWidth = mDrawable.getIntrinsicWidth();
+ return mPositionX >= clipLeft - handleWidth * 0.75f &&
+ mPositionX <= clipRight + handleWidth * 0.25f &&
+ mPositionY >= clipTop && mPositionY <= clipBottom;
+ }
+
+ private void moveTo(int x, int y) {
+ mPositionX = x - TextView.this.mScrollX;
+ mPositionY = y - TextView.this.mScrollY;
+ if (isPositionInBounds()) {
+ if (mContainer.isShowing()){
+ final int[] coords = mTempCoords;
+ TextView.this.getLocationOnScreen(coords);
+ coords[0] += mPositionX;
+ coords[1] += mPositionY;
+ mContainer.update(coords[0], coords[1], mRight - mLeft, mBottom - mTop);
+ } else {
+ show();
+ }
+ } else {
+ hide();
+ }
+ }
+
+ @Override
+ public void onDraw(Canvas c) {
+ mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
+ if (mPositionOnTop) {
+ c.save();
+ c.rotate(180, (mRight - mLeft) / 2, (mBottom - mTop) / 2);
+ mDrawable.draw(c);
+ c.restore();
+ } else {
+ mDrawable.draw(c);
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mIsDragging = true;
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ final float rawX = ev.getRawX();
+ final float rawY = ev.getRawY();
+ final int[] coords = mTempCoords;
+ TextView.this.getLocationOnScreen(coords);
+ final int x = (int) (rawX - coords[0] + 0.5f);
+ final int y = (int) (rawY - coords[1] + 0.5f);
+ mController.updatePosition(x, y);
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mIsDragging = false;
+ }
+ return true;
+ }
+
+ public boolean isDragging() {
+ return mIsDragging;
}
void positionAtCursor(final int offset, boolean bottom) {
- final int drawableWidth = mDrawable.getIntrinsicWidth();
- final int drawableHeight = mDrawable.getIntrinsicHeight();
+ final int width = mDrawable.getIntrinsicWidth();
+ final int height = mDrawable.getIntrinsicHeight();
final int line = mLayout.getLineForOffset(offset);
final int lineTop = mLayout.getLineTop(line);
final int lineBottom = mLayout.getLineBottom(line);
- mHotSpotVerticalPosition = lineTop;
-
final Rect bounds = sCursorControllerTempRect;
- bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - drawableWidth / 2.0)
- + mScrollX;
- bounds.top = (bottom ? lineBottom : lineTop) + mScrollY;
+ bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - width / 2.0)
+ + TextView.this.mScrollX;
+ bounds.top = (bottom ? lineBottom : lineTop) + TextView.this.mScrollY;
- mTopExtension = bottom ? 0 : drawableHeight / 2;
- mBottomExtension = 0; //drawableHeight / 4;
-
- // Extend touch region up when editing the last line of text (or a single line) so that
- // it is easier to grab.
- if (line == mLayout.getLineCount() - 1) {
- mTopExtension = (lineBottom - lineTop) - drawableHeight / 2;
- }
-
- bounds.right = bounds.left + drawableWidth;
- bounds.bottom = bounds.top + drawableHeight;
+ bounds.right = bounds.left + width;
+ bounds.bottom = bounds.top + height;
convertFromViewportToContentCoordinates(bounds);
- invalidate();
- mDrawable.setBounds(bounds);
- invalidate();
- }
-
- boolean hasFingerOn(float x, float y) {
- // Simulate a 'fat finger' to ease grabbing of the controller.
- // Expands according to controller image size instead of using dip distance.
- // Assumes controller imager has a sensible size, proportionnal to screen density.
- final int drawableWidth = mDrawable.getIntrinsicWidth();
- final Rect fingerRect = sCursorControllerTempRect;
- fingerRect.set((int) (x - drawableWidth / 2.0),
- (int) (y - mBottomExtension),
- (int) (x + drawableWidth / 2.0),
- (int) (y + mTopExtension));
- fingerRect.offset(mScrollX, mScrollY);
- return Rect.intersects(mDrawable.getBounds(), fingerRect);
- }
-
- void invalidate() {
- final Rect bounds = mDrawable.getBounds();
- TextView.this.invalidate(bounds.left, bounds.top,
- bounds.right, bounds.bottom);
- }
-
- void postInvalidate() {
- final Rect bounds = mDrawable.getBounds();
- TextView.this.postInvalidate(bounds.left, bounds.top,
- bounds.right, bounds.bottom);
- }
-
- void postInvalidateDelayed(long delay) {
- final Rect bounds = mDrawable.getBounds();
- TextView.this.postInvalidateDelayed(delay, bounds.left, bounds.top,
- bounds.right, bounds.bottom);
+ moveTo(bounds.left, bounds.top);
}
}
class InsertionPointCursorController implements CursorController {
- private static final int DELAY_BEFORE_FADE_OUT = 2100;
+ private static final int DELAY_BEFORE_FADE_OUT = 4100;
- // Whether or not the cursor control is currently visible
- private boolean mIsVisible = false;
- // Starting time of the fade timer
- private long mFadeOutTimerStart;
// The cursor controller image
- private final Handle mHandle;
- // Used to detect a tap (vs drag) on the controller
- private long mOnDownTimerStart;
+ private final HandleView mHandle;
// Offset between finger hot point on cursor controller and actual cursor
private float mOffsetX, mOffsetY;
+ private final Runnable mHider = new Runnable() {
+ public void run() {
+ hide();
+ }
+ };
+
InsertionPointCursorController() {
Resources res = mContext.getResources();
- mHandle = new Handle(res.getDrawable(mTextSelectHandleRes));
+ mHandle = new HandleView(this, res.getDrawable(mTextSelectHandleRes));
}
public void show() {
- updateDrawablePosition();
- // Has to be done after updateDrawablePosition, so that previous position invalidate
- // in only done if necessary.
- mIsVisible = true;
- updateOverlay();
+ updatePosition();
+ mHandle.show();
+ hideDelayed(DELAY_BEFORE_FADE_OUT);
}
public void hide() {
- if (mIsVisible) {
- long time = System.currentTimeMillis();
- // Start fading out, only if not already in progress
- if (time - mFadeOutTimerStart < DELAY_BEFORE_FADE_OUT) {
- mFadeOutTimerStart = time - DELAY_BEFORE_FADE_OUT;
- mHandle.postInvalidate();
- }
- }
+ mHandle.hide();
+ TextView.this.removeCallbacks(mHider);
+ }
+
+ private void hideDelayed(int msec) {
+ TextView.this.removeCallbacks(mHider);
+ TextView.this.postDelayed(mHider, msec);
}
public boolean isShowing() {
- return mIsVisible;
- }
-
- public void draw(Canvas canvas) {
- if (mIsVisible) {
- int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
- if (time <= DELAY_BEFORE_FADE_OUT) {
- mHandle.postInvalidateDelayed(DELAY_BEFORE_FADE_OUT - time);
- } else {
- time -= DELAY_BEFORE_FADE_OUT;
- if (time <= FADE_OUT_DURATION) {
- final int alpha = (int)
- ((255.0 * (FADE_OUT_DURATION - time)) / FADE_OUT_DURATION);
- mHandle.mDrawable.setAlpha(alpha);
- mHandle.postInvalidateDelayed(30);
- } else {
- mHandle.mDrawable.setAlpha(0);
- mIsVisible = false;
- updateOverlay();
- }
- }
- mHandle.mDrawable.draw(canvas);
- }
+ return mHandle.isShowing();
}
public void updatePosition(int x, int y) {
@@ -7922,81 +7934,22 @@
if (offset != previousOffset) {
Selection.setSelection((Spannable) mText, offset);
- updateDrawablePosition();
+ updatePosition();
}
+ hideDelayed(DELAY_BEFORE_FADE_OUT);
}
- private void updateDrawablePosition() {
- if (mIsVisible) {
- // Clear previous cursor controller before bounds are updated
- mHandle.postInvalidate();
- }
-
+ public void updatePosition() {
final int offset = getSelectionStart();
if (offset < 0) {
// Should never happen, safety check.
Log.w(LOG_TAG, "Update cursor controller position called with no cursor");
- mIsVisible = false;
- updateOverlay();
+ hide();
return;
}
mHandle.positionAtCursor(offset, true);
-
- mFadeOutTimerStart = System.currentTimeMillis();
- mHandle.mDrawable.setAlpha(255);
- }
-
- public boolean onTouchEvent(MotionEvent event) {
- if (isFocused() && isTextEditable() && mIsVisible) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN : {
- final float x = event.getX();
- final float y = event.getY();
-
- if (mHandle.hasFingerOn(x, y)) {
- show();
-
- if (mMovement instanceof ArrowKeyMovementMethod) {
- ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
- }
-
- if (mParent != null) {
- // Prevent possible scrollView parent from scrolling, so that
- // we can use auto-scrolling.
- mParent.requestDisallowInterceptTouchEvent(true);
- }
-
- final Rect bounds = mHandle.mDrawable.getBounds();
- mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
- mOffsetY = mHandle.mHotSpotVerticalPosition - y;
-
- mOffsetX += viewportToContentHorizontalOffset();
- mOffsetY += viewportToContentVerticalOffset();
-
- mOnDownTimerStart = event.getEventTime();
- return true;
- }
- return false;
- }
-
- case MotionEvent.ACTION_UP : {
- int time = (int) (event.getEventTime() - mOnDownTimerStart);
-
- if (time <= ViewConfiguration.getTapTimeout()) {
- // A tap on the controller (not a drag) will move the cursor
- int offset = getOffset((int) event.getX(), (int) event.getY());
- Selection.setSelection((Spannable) mText, offset);
-
- // Modified by cancelLongPress and prevents the cursor from changing
- mScrolled = false;
- }
- break;
- }
- }
- }
- return false;
}
public float getOffsetX() {
@@ -8006,88 +7959,59 @@
public float getOffsetY() {
return mOffsetY;
}
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ return false;
+ }
}
class SelectionModifierCursorController implements CursorController {
- // Whether or not the selection controls are currently visible
- private boolean mIsVisible = false;
- // Whether that start or the end of selection controller is dragged
- private boolean mStartIsDragged = false;
- // Starting time of the fade timer
- private long mFadeOutTimerStart;
// The cursor controller images
- private final Handle mStartHandle, mEndHandle;
+ private HandleView mStartHandle, mEndHandle;
// Offset between finger hot point on active cursor controller and actual cursor
private float mOffsetX, mOffsetY;
// The offsets of that last touch down event. Remembered to start selection there.
private int mMinTouchOffset, mMaxTouchOffset;
+ // Whether selection anchors are active
+ private boolean mIsShowing;
SelectionModifierCursorController() {
Resources res = mContext.getResources();
- mStartHandle = new Handle(res.getDrawable(mTextSelectHandleLeftRes));
- mEndHandle = new Handle(res.getDrawable(mTextSelectHandleRightRes));
+ mStartHandle = new HandleView(this, res.getDrawable(mTextSelectHandleLeftRes));
+ mEndHandle = new HandleView(this, res.getDrawable(mTextSelectHandleRightRes));
}
public void show() {
- updateDrawablesPositions();
- // Has to be done after updateDrawablePositions, so that previous position invalidate
- // in only done if necessary.
- mIsVisible = true;
- updateOverlay();
- mFadeOutTimerStart = -1;
+ mIsShowing = true;
+ updatePosition();
+ mStartHandle.show();
+ mEndHandle.show();
hideInsertionPointCursorController();
}
public void hide() {
- if (mIsVisible && (mFadeOutTimerStart < 0)) {
- mFadeOutTimerStart = System.currentTimeMillis();
- mStartHandle.postInvalidate();
- mEndHandle.postInvalidate();
- }
+ mStartHandle.hide();
+ mEndHandle.hide();
+ mIsShowing = false;
}
public boolean isShowing() {
- return mIsVisible;
+ return mIsShowing;
}
public void cancelFadeOutAnimation() {
- mIsVisible = false;
- updateOverlay();
- mStartHandle.postInvalidate();
- mEndHandle.postInvalidate();
- }
-
- public void draw(Canvas canvas) {
- if (mIsVisible) {
- if (mFadeOutTimerStart >= 0) {
- int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
- if (time <= FADE_OUT_DURATION) {
- final int alpha = 255 * (FADE_OUT_DURATION - time) / FADE_OUT_DURATION;
- mStartHandle.mDrawable.setAlpha(alpha);
- mEndHandle.mDrawable.setAlpha(alpha);
- mStartHandle.postInvalidateDelayed(30);
- mEndHandle.postInvalidateDelayed(30);
- } else {
- mStartHandle.mDrawable.setAlpha(0);
- mEndHandle.mDrawable.setAlpha(0);
- mIsVisible = false;
- updateOverlay();
- }
- }
- mStartHandle.mDrawable.draw(canvas);
- mEndHandle.mDrawable.draw(canvas);
- }
+ hide();
}
public void updatePosition(int x, int y) {
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
- final int previousOffset = mStartIsDragged ? selectionStart : selectionEnd;
+ final int previousOffset = mStartHandle.isDragging() ? selectionStart : selectionEnd;
int offset = getHysteresisOffset(x, y, previousOffset);
// Handle the case where start and end are swapped, making sure start <= end
- if (mStartIsDragged) {
+ if (mStartHandle.isDragging()) {
if (offset <= selectionEnd) {
if (selectionStart == offset) {
return; // no change, no need to redraw;
@@ -8096,7 +8020,9 @@
} else {
selectionStart = selectionEnd;
selectionEnd = offset;
- mStartIsDragged = false;
+ HandleView temp = mStartHandle;
+ mStartHandle = mEndHandle;
+ mEndHandle = temp;
}
} else {
if (offset >= selectionStart) {
@@ -8107,43 +8033,35 @@
} else {
selectionEnd = selectionStart;
selectionStart = offset;
- mStartIsDragged = true;
+ HandleView temp = mStartHandle;
+ mStartHandle = mEndHandle;
+ mEndHandle = temp;
}
}
Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
- updateDrawablesPositions();
+ updatePosition();
}
- private void updateDrawablesPositions() {
- if (mIsVisible) {
- // Clear previous cursor controller before bounds are updated
- mStartHandle.postInvalidate();
- mEndHandle.postInvalidate();
- }
-
+ public void updatePosition() {
final int selectionStart = getSelectionStart();
final int selectionEnd = getSelectionEnd();
if ((selectionStart < 0) || (selectionEnd < 0)) {
// Should never happen, safety check.
Log.w(LOG_TAG, "Update selection controller position called with no cursor");
- mIsVisible = false;
- updateOverlay();
+ hide();
return;
}
- boolean oneLineSelection =
- mLayout.getLineForOffset(selectionStart) == mLayout.getLineForOffset(selectionEnd);
+ boolean oneLineSelection = mLayout.getLineForOffset(selectionStart) ==
+ mLayout.getLineForOffset(selectionEnd);
mStartHandle.positionAtCursor(selectionStart, oneLineSelection);
mEndHandle.positionAtCursor(selectionEnd, true);
-
- mStartHandle.mDrawable.setAlpha(255);
- mEndHandle.mDrawable.setAlpha(255);
}
public boolean onTouchEvent(MotionEvent event) {
- if (isTextEditable()) {
+ if (isFocused() && isTextEditable()) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
final int x = (int) event.getX();
@@ -8152,34 +8070,6 @@
// Remember finger down position, to be able to start selection from there
mMinTouchOffset = mMaxTouchOffset = mLastTouchOffset = getOffset(x, y);
- if (mIsVisible) {
- if (mMovement instanceof ArrowKeyMovementMethod) {
- boolean isOnStart = mStartHandle.hasFingerOn(x, y);
- boolean isOnEnd = mEndHandle.hasFingerOn(x, y);
- if (isOnStart || isOnEnd) {
- if (mParent != null) {
- // Prevent possible scrollView parent from scrolling, so
- // that we can use auto-scrolling.
- mParent.requestDisallowInterceptTouchEvent(true);
- }
-
- // In case both controllers are under finger (very small
- // selection region), arbitrarily pick end controller.
- mStartIsDragged = !isOnEnd;
- final Handle draggedHandle =
- mStartIsDragged ? mStartHandle : mEndHandle;
- final Rect bounds = draggedHandle.mDrawable.getBounds();
- mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
- mOffsetY = draggedHandle.mHotSpotVerticalPosition - y;
-
- mOffsetX += viewportToContentHorizontalOffset();
- mOffsetY += viewportToContentVerticalOffset();
-
- ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
- return true;
- }
- }
- }
break;
case MotionEvent.ACTION_POINTER_DOWN:
@@ -8230,7 +8120,7 @@
* @return true iff this controller is currently used to move the selection start.
*/
public boolean isSelectionStartDragged() {
- return mIsVisible && mStartIsDragged;
+ return mStartHandle.isDragging();
}
}
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 344669c..ee44747 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -226,10 +226,8 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static SkShader* RadialGradient_create1(JNIEnv* env, jobject,
- float x, float y, float radius,
- jintArray colorArray, jfloatArray posArray, int tileMode)
-{
+static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius,
+ jintArray colorArray, jfloatArray posArray, int tileMode) {
SkPoint center;
center.set(SkFloatToScalar(x), SkFloatToScalar(y));
@@ -259,10 +257,8 @@
return shader;
}
-static SkShader* RadialGradient_create2(JNIEnv* env, jobject,
- float x, float y, float radius,
- int color0, int color1, int tileMode)
-{
+static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius,
+ int color0, int color1, int tileMode) {
SkPoint center;
center.set(SkFloatToScalar(x), SkFloatToScalar(y));
@@ -276,11 +272,65 @@
return s;
}
+static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
+ float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) {
+#ifdef USE_OPENGL_RENDERER
+ size_t count = env->GetArrayLength(colorArray);
+ const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
+
+ jfloat* storedPositions = new jfloat[count];
+ uint32_t* storedColors = new uint32_t[count];
+ for (size_t i = 0; i < count; i++) {
+ storedColors[i] = static_cast<uint32_t>(colorValues[i]);
+ }
+
+ if (posArray) {
+ AutoJavaFloatArray autoPos(env, posArray, count);
+ const float* posValues = autoPos.ptr();
+ for (size_t i = 0; i < count; i++) {
+ storedPositions[i] = posValues[i];
+ }
+ } else {
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
+ }
+
+ SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
+ storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
+ (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+ env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
+ return skiaShader;
+#else
+ return NULL;
+#endif
+}
+
+static SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
+ float x, float y, float radius, int color0, int color1, int tileMode) {
+#ifdef USE_OPENGL_RENDERER
+ float* storedPositions = new float[2];
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
+
+ uint32_t* storedColors = new uint32_t[2];
+ storedColors[0] = static_cast<uint32_t>(color0);
+ storedColors[1] = static_cast<uint32_t>(color1);
+
+ SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
+ storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
+ (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+ return skiaShader;
+#else
+ return NULL;
+#endif
+}
+
///////////////////////////////////////////////////////////////////////////////
static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y,
- jintArray jcolors, jfloatArray jpositions)
-{
+ jintArray jcolors, jfloatArray jpositions) {
size_t count = env->GetArrayLength(jcolors);
const jint* colors = env->GetIntArrayElements(jcolors, NULL);
@@ -307,8 +357,7 @@
}
static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
- int color0, int color1)
-{
+ int color0, int color1) {
SkColor colors[2];
colors[0] = color0;
colors[1] = color1;
@@ -437,22 +486,24 @@
};
static JNINativeMethod gRadialGradientMethods[] = {
- {"nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 },
- {"nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 }
+ { "nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 },
+ { "nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 },
+ { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 },
+ { "nativePostCreate2", "(IFFFIII)I", (void*)RadialGradient_postCreate2 }
};
static JNINativeMethod gSweepGradientMethods[] = {
- {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
- {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 },
+ { "nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
+ { "nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 },
{ "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 },
{ "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 }
};
static JNINativeMethod gComposeShaderMethods[] = {
- {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 },
- {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 },
- {"nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 },
- {"nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 }
+ { "nativeCreate1", "(III)I", (void*)ComposeShader_create1 },
+ { "nativeCreate2", "(III)I", (void*)ComposeShader_create2 },
+ { "nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 },
+ { "nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 }
};
#include <android_runtime/AndroidRuntime.h>
diff --git a/core/res/res/layout/simple_list_item_2.xml b/core/res/res/layout/simple_list_item_2.xml
index 5eab54e..c87922c 100644
--- a/core/res/res/layout/simple_list_item_2.xml
+++ b/core/res/res/layout/simple_list_item_2.xml
@@ -15,8 +15,6 @@
-->
<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
- android:paddingTop="2dip"
- android:paddingBottom="2dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
diff --git a/core/res/res/layout/simple_list_item_activated_1.xml b/core/res/res/layout/simple_list_item_activated_1.xml
new file mode 100644
index 0000000..8416df2
--- /dev/null
+++ b/core/res/res/layout/simple_list_item_activated_1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+/>
diff --git a/core/res/res/layout/simple_list_item_activated_2.xml b/core/res/res/layout/simple_list_item_activated_2.xml
new file mode 100644
index 0000000..2ffbf02
--- /dev/null
+++ b/core/res/res/layout/simple_list_item_activated_2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingTop="2dip"
+ android:paddingBottom="2dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:mode="twoLine"
+>
+
+ <TextView android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="6dip"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+
+ <TextView android:id="@android:id/text2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/text1"
+ android:layout_alignLeft="@android:id/text1"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+
+</TwoLineListItem>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 779a33f..19b76ab 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -466,6 +466,9 @@
<attr name="quickContactBadgeStyleSmallWindowMedium" format="reference" />
<!-- Default quickcontact badge style with large quickcontact window. -->
<attr name="quickContactBadgeStyleSmallWindowLarge" format="reference" />
+ <!-- Reference to a style that will be used for the window containing a text
+ selection anchor. -->
+ <attr name="textSelectHandleWindowStyle" format="reference" />
<!-- Default ListPopupWindow style. -->
<attr name="listPopupWindowStyle" format="reference" />
<!-- Default PopupMenu style. -->
@@ -2355,6 +2358,7 @@
</declare-styleable>
<declare-styleable name="PopupWindow">
<attr name="popupBackground" format="reference|color" />
+ <attr name="windowAnimationStyle" />
</declare-styleable>
<declare-styleable name="ViewAnimator">
<!-- Identifier for the animation to use when a view is shown. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6f53677..cdeb899 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1255,6 +1255,7 @@
<public type="attr" name="textSelectHandleLeft" id="0x010102c5" />
<public type="attr" name="textSelectHandleRight" id="0x010102c6" />
<public type="attr" name="textSelectHandle" id="0x010102c7" />
+ <public type="attr" name="textSelectHandleWindowStyle" id="0x010102c8" />
<public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />
@@ -1376,6 +1377,16 @@
<!-- A simple ListView item layout which can contain text and support (single or multiple) item selection. -->
<public type="layout" name="simple_selectable_list_item" />
+ <!-- A version of {@link #simple_list_item_1} that is able to change its
+ background state to indicate when it is activated (that is checked by
+ a ListView). -->
+ <public type="layout" name="simple_list_item_activated_1" />
+
+ <!-- A version of {@link #simple_list_item_2} that is able to change its
+ background state to indicate when it is activated (that is checked by
+ a ListView). -->
+ <public type="layout" name="simple_list_item_activated_2" />
+
<public type="style" name="Theme.WithActionBar" />
<public type="style" name="Widget.Spinner.DropDown" />
<public type="style" name="Widget.ActionButton" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e8343f1..c37bb66 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -881,6 +881,17 @@
<item name="android:background">@android:drawable/bottom_bar</item>
</style>
+ <!-- Style for the small popup windows that contain text selection anchors. -->
+ <style name="Widget.TextSelectHandle">
+ <item name="android:windowAnimationStyle">@android:style/Animation.TextSelectHandle</item>
+ </style>
+
+ <!-- Style for animating text selection handles. -->
+ <style name="Animation.TextSelectHandle">
+ <item name="windowEnterAnimation">@android:anim/fade_in</item>
+ <item name="windowExitAnimation">@android:anim/fade_out</item>
+ </style>
+
<style name="Widget.ActionBar">
<item name="android:background">@android:drawable/action_bar_background</item>
<item name="android:displayOptions">useLogo</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index fd39179..9425fc4 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -156,6 +156,7 @@
<item name="textSelectHandleLeft">@android:drawable/text_select_handle_middle</item>
<item name="textSelectHandleRight">@android:drawable/text_select_handle_middle</item>
<item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleWindowStyle">@android:style/Widget.TextSelectHandle</item>
<!-- Widget styles -->
<item name="absListViewStyle">@android:style/Widget.AbsListView</item>
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
index 0f7351a..c698e99 100644
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
+++ b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
@@ -601,7 +601,7 @@
mTestRunErrorMessage = errorMessage;
}
- public void testRunStarted(int testCount) {
+ public void testRunStarted(String runName, int testCount) {
// ignore
}
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index b4e902d..897762c 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -40,6 +40,8 @@
throw new IllegalArgumentException("color and position arrays must be of equal length");
}
native_instance = nativeCreate1(x, y, radius, colors, positions, tile.nativeInt);
+ native_shader = nativePostCreate1(native_instance, x, y, radius, colors, positions,
+ tile.nativeInt);
}
/** Create a shader that draws a radial gradient given the center and radius.
@@ -56,11 +58,18 @@
throw new IllegalArgumentException("radius must be > 0");
}
native_instance = nativeCreate2(x, y, radius, color0, color1, tile.nativeInt);
+ native_shader = nativePostCreate2(native_instance, x, y, radius, color0, color1,
+ tile.nativeInt);
}
private static native int nativeCreate1(float x, float y, float radius,
- int colors[], float positions[], int tileMode);
+ int colors[], float positions[], int tileMode);
private static native int nativeCreate2(float x, float y, float radius,
- int color0, int color1, int tileMode);
+ int color0, int color1, int tileMode);
+
+ private static native int nativePostCreate1(int native_shader, float x, float y, float radius,
+ int colors[], float positions[], int tileMode);
+ private static native int nativePostCreate2(int native_shader, float x, float y, float radius,
+ int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 3198e3f..715e3fb 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -32,6 +32,9 @@
}
public int getID() {
+ if (mDestroyed) {
+ throw new IllegalStateException("using a destroyed object.");
+ }
return mID;
}
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index 0f986a0..69021d8c 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -22,45 +22,18 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AString.h>
+#include <utils/Log.h>
namespace android {
-enum LogType {
- VERBOSE,
- INFO,
- WARNING,
- ERROR,
- FATAL,
-};
-
-struct Logger {
- Logger(LogType type);
- virtual ~Logger();
-
- template<class T> Logger &operator<<(const T &x) {
- mMessage.append(x);
-
- return *this;
- }
-
-private:
- android::AString mMessage;
- LogType mLogType;
-
- DISALLOW_EVIL_CONSTRUCTORS(Logger);
-};
-
-const char *LeafName(const char *s);
-
-#undef LOG
-#define LOG(type) Logger(type) << LeafName(__FILE__) << ":" << __LINE__ << " "
+#define LITERAL_TO_STRING_INTERNAL(x) #x
+#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
#define CHECK(condition) \
- do { \
- if (!(condition)) { \
- LOG(FATAL) << "CHECK(" #condition ") failed."; \
- } \
- } while (false)
+ LOG_ALWAYS_FATAL_IF( \
+ !(condition), \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \
+ " CHECK(" #condition ") failed.")
#define MAKE_COMPARATOR(suffix,op) \
template<class A, class B> \
@@ -85,8 +58,10 @@
do { \
AString ___res = Compare_##suffix(x, y); \
if (!___res.empty()) { \
- LOG(FATAL) << "CHECK_" #suffix "(" #x "," #y ") failed: " \
- << ___res; \
+ LOG_ALWAYS_FATAL( \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \
+ " CHECK_" #suffix "( " #x "," #y ") failed: %s", \
+ ___res.c_str()); \
} \
} while (false)
@@ -97,7 +72,7 @@
#define CHECK_GE(x,y) CHECK_OP(x,y,GE,>=)
#define CHECK_GT(x,y) CHECK_OP(x,y,GT,>)
-#define TRESPASS() LOG(FATAL) << "Should not be here."
+#define TRESPASS() LOG_ALWAYS_FATAL("Should not be here.")
} // namespace android
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index 7d90866..3f00b78 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -205,6 +205,7 @@
int pollInner(int timeoutMillis);
+ static void initTLSKey();
static void threadDestructor(void *st);
};
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 264ad3d..c698b5a 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -144,6 +144,12 @@
return data[kTranslateY];
}
+void Matrix4::multiply(float v) {
+ for (int i = 0; i < 16; i++) {
+ data[i] *= v;
+ }
+}
+
void Matrix4::loadTranslate(float x, float y, float z) {
loadIdentity();
data[kTranslateX] = x;
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index c247a67..0608efe 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -83,6 +83,8 @@
load(u);
}
+ void multiply(float v);
+
void translate(float x, float y, float z) {
Matrix4 u;
u.loadTranslate(x, y, z);
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index bcc1edf..3e9412c 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -40,9 +40,12 @@
"uniform vec2 gradientStart;\n"
"uniform mat4 screenSpace;\n",
// Circular
- "",
+ "uniform vec2 gradientStart;\n"
+ "uniform mat4 gradientMatrix;\n"
+ "uniform mat4 screenSpace;\n",
// Sweep
"uniform vec2 gradientStart;\n"
+ "uniform mat4 gradientMatrix;\n"
"uniform mat4 screenSpace;\n"
};
const char* gVS_Header_Uniforms_HasBitmap =
@@ -56,7 +59,7 @@
// Linear
"varying float index;\n",
// Circular
- "",
+ "varying vec2 circular;\n",
// Sweep
"varying vec2 sweep;\n"
};
@@ -69,10 +72,11 @@
" vec4 location = screenSpace * position;\n"
" index = dot(location.xy - gradientStart, gradient) * gradientLength;\n",
// Circular
- "",
+ " vec4 location = screenSpace * position;\n"
+ " circular = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n",
// Sweep
" vec4 location = screenSpace * position;\n"
- " sweep = location.xy - gradientStart;\n"
+ " sweep = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n"
};
const char* gVS_Main_OutBitmapTexCoords =
" vec4 bitmapCoords = textureTransform * position;\n"
@@ -98,6 +102,7 @@
// Linear
"uniform sampler2D gradientSampler;\n",
// Circular
+ "uniform float gradientRadius;\n"
"uniform sampler2D gradientSampler;\n",
// Sweep
"uniform sampler2D gradientSampler;\n"
@@ -129,7 +134,8 @@
// Linear
" vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
// Circular
- "",
+ " float index = length(circular) * gradientRadius;\n"
+ " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
// Sweep
" float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
" vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n"
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index c5d9767..9e1f6c2 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -209,6 +209,30 @@
}
///////////////////////////////////////////////////////////////////////////////
+// Circular gradient shader
+///////////////////////////////////////////////////////////////////////////////
+
+SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
+ uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+ SkMatrix* matrix, bool blend):
+ SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
+ tileMode, matrix, blend),
+ mRadius(radius) {
+}
+
+void SkiaCircularGradientShader::describe(ProgramDescription& description,
+ const Extensions& extensions) {
+ description.hasGradient = true;
+ description.gradientType = ProgramDescription::kGradientCircular;
+}
+
+void SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView,
+ const Snapshot& snapshot, GLuint* textureUnit) {
+ SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit);
+ glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius);
+}
+
+///////////////////////////////////////////////////////////////////////////////
// Sweep gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -219,6 +243,13 @@
mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
}
+SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
+ float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+ SkMatrix* matrix, bool blend):
+ SkiaShader(type, key, tileMode, tileMode, matrix, blend),
+ mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
+}
+
SkiaSweepGradientShader::~SkiaSweepGradientShader() {
delete[] mColors;
delete[] mPositions;
@@ -243,10 +274,15 @@
float left = mX;
float top = mY;
+ mat4 shaderMatrix;
if (mMatrix) {
- mat4 shaderMatrix(*mMatrix);
+ shaderMatrix.load(*mMatrix);
shaderMatrix.mapPoint(left, top);
}
+
+ mat4 copy(shaderMatrix);
+ shaderMatrix.loadInverse(copy);
+
snapshot.transform->mapPoint(left, top);
mat4 screenSpace(*snapshot.transform);
@@ -255,6 +291,7 @@
// Uniforms
bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
glUniform1i(program->getUniform("gradientSampler"), textureSlot);
+ glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]);
glUniform2f(program->getUniform("gradientStart"), left, top);
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index b67bfee..0023c46 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -152,12 +152,15 @@
SkShader* key, SkMatrix* matrix, bool blend);
~SkiaSweepGradientShader();
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
+ virtual void describe(ProgramDescription& description, const Extensions& extensions);
+ virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
GLuint* textureUnit);
void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
-private:
+protected:
+ SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
+ int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+
float mX, mY;
uint32_t* mColors;
float* mPositions;
@@ -165,6 +168,21 @@
}; // struct SkiaSweepGradientShader
/**
+ * A shader that draws a circular gradient.
+ */
+struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
+ SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions,
+ int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+
+ void describe(ProgramDescription& description, const Extensions& extensions);
+ void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
+ GLuint* textureUnit);
+
+private:
+ float mRadius;
+}; // struct SkiaCircularGradientShader
+
+/**
* A shader that draws two shaders, composited with an xfermode.
*/
struct SkiaComposeShader: public SkiaShader {
diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
index b6148eff..39bd2c4 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
@@ -3,7 +3,9 @@
#pragma rs export_func(rs_primitives_test)
// Testing primitive types
-static float floatTest = 1.0;
+#pragma rs export_var(floatTest)
+#pragma rs export_var(doubleTest)
+static float floatTest = 1.99f;
static double doubleTest = 2.05;
static char charTest = -8;
static short shortTest = -16;
@@ -16,7 +18,7 @@
bool failed = false;
start();
- _RS_ASSERT(floatTest == 1.0);
+ _RS_ASSERT(floatTest == 1.99f);
_RS_ASSERT(doubleTest == 2.05);
_RS_ASSERT(charTest == -8);
_RS_ASSERT(shortTest == -16);
diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp
index b46279e..d2dd6eb 100644
--- a/libs/utils/Looper.cpp
+++ b/libs/utils/Looper.cpp
@@ -24,16 +24,15 @@
namespace android {
-static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static bool gHaveTLS = false;
-static pthread_key_t gTLS = 0;
-
// Hint for number of file descriptors to be associated with the epoll instance.
static const int EPOLL_SIZE_HINT = 8;
// Maximum number of file descriptors for which to retrieve poll events each iteration.
static const int EPOLL_MAX_EVENTS = 16;
+static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
+static pthread_key_t gTLSKey = 0;
+
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks),
mResponseIndex(0) {
@@ -56,6 +55,7 @@
errno);
struct epoll_event eventItem;
+ memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
@@ -69,6 +69,11 @@
close(mEpollFd);
}
+void Looper::initTLSKey() {
+ int result = pthread_key_create(& gTLSKey, threadDestructor);
+ LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
+}
+
void Looper::threadDestructor(void *st) {
Looper* const self = static_cast<Looper*>(st);
if (self != NULL) {
@@ -83,7 +88,7 @@
looper->incStrong((void*)threadDestructor);
}
- pthread_setspecific(gTLS, looper.get());
+ pthread_setspecific(gTLSKey, looper.get());
if (old != NULL) {
old->decStrong((void*)threadDestructor);
@@ -91,17 +96,10 @@
}
sp<Looper> Looper::getForThread() {
- if (!gHaveTLS) {
- pthread_mutex_lock(&gTLSMutex);
- if (pthread_key_create(&gTLS, threadDestructor) != 0) {
- pthread_mutex_unlock(&gTLSMutex);
- return NULL;
- }
- gHaveTLS = true;
- pthread_mutex_unlock(&gTLSMutex);
- }
+ int result = pthread_once(& gTLSOnce, initTLSKey);
+ LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
- return (Looper*)pthread_getspecific(gTLS);
+ return (Looper*)pthread_getspecific(gTLSKey);
}
sp<Looper> Looper::prepare(int opts) {
@@ -331,6 +329,7 @@
request.data = data;
struct epoll_event eventItem;
+ memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = epollEvents;
eventItem.data.fd = fd;
diff --git a/media/java/android/media/Visualizer.java b/media/java/android/media/Visualizer.java
index 453fc04..33222ff 100755
--- a/media/java/android/media/Visualizer.java
+++ b/media/java/android/media/Visualizer.java
@@ -218,13 +218,16 @@
public int setEnabled(boolean enabled)
throws IllegalStateException {
synchronized (mStateLock) {
- if ((enabled && mState != STATE_INITIALIZED) ||
- (!enabled && mState != STATE_ENABLED)) {
+ if (mState == STATE_UNINITIALIZED) {
throw(new IllegalStateException("setEnabled() called in wrong state: "+mState));
}
- int status = native_setEnabled(enabled);
- if (status == SUCCESS) {
- mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
+ int status = SUCCESS;
+ if ((enabled && (mState == STATE_INITIALIZED)) ||
+ (!enabled && (mState == STATE_ENABLED))) {
+ status = native_setEnabled(enabled);
+ if (status == SUCCESS) {
+ mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
+ }
}
return status;
}
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 8ab57c93..03a6bbb 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -239,6 +239,24 @@
}
// all code below assumes stereo 16 bit PCM output and input
+
+ // derive capture scaling factor from peak value in current buffer
+ // this gives more interesting captures for display.
+ int32_t shift = 32;
+ for (size_t i = 0; i < inBuffer->frameCount; i++) {
+ int32_t smp = inBuffer->s16[i];
+ if (smp < 0) smp = -smp;
+ int32_t clz = __builtin_clz(smp);
+ if (shift > clz) shift = clz;
+ }
+ // never scale by less than 8 to avoid returning unaltered PCM signal.
+ // add one to combine the division by 2 needed after summing left and right channels below
+ if (20 > shift) {
+ shift = (31 - 8 + 1) - shift;
+ } else {
+ shift = (3 + 1);
+ }
+
uint32_t captIdx;
uint32_t inIdx;
uint8_t *buf = pContext->mCaptureBuf[pContext->mCurrentBuf];
@@ -246,7 +264,7 @@
inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
inIdx++, captIdx++) {
int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
- smp = (smp + (1 << 8)) >> 9;
+ smp = (smp + (1 << (shift - 1))) >> shift;
buf[captIdx] = ((uint8_t)smp)^0x80;
}
pContext->mCaptureIdx = captIdx;
@@ -369,7 +387,7 @@
case VISU_CMD_CAPTURE:
- if (pReplyData == NULL || *replySize != (int)pContext->mCaptureSize) {
+ if (pReplyData == NULL || *replySize != pContext->mCaptureSize) {
LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
*replySize, pContext->mCaptureSize);
return -EINVAL;
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 9171aab..3a0fc41 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -132,7 +132,7 @@
}
void PageCache::copy(size_t from, void *data, size_t size) {
- LOG(VERBOSE) << "copy from " << from << " size " << size;
+ LOGV("copy from %d size %d", from, size);
CHECK_LE(from + size, mTotalSize);
@@ -228,7 +228,7 @@
}
void NuCachedSource2::fetchInternal() {
- LOG(VERBOSE) << "fetchInternal";
+ LOGV("fetchInternal");
CHECK_EQ(mFinalStatus, (status_t)OK);
@@ -240,11 +240,11 @@
Mutex::Autolock autoLock(mLock);
if (n < 0) {
- LOG(ERROR) << "source returned error " << n;
+ LOGE("source returned error %ld", n);
mFinalStatus = n;
mCache->releasePage(page);
} else if (n == 0) {
- LOG(INFO) << "ERROR_END_OF_STREAM";
+ LOGI("ERROR_END_OF_STREAM");
mFinalStatus = ERROR_END_OF_STREAM;
mCache->releasePage(page);
} else {
@@ -254,10 +254,10 @@
}
void NuCachedSource2::onFetch() {
- LOG(VERBOSE) << "onFetch";
+ LOGV("onFetch");
if (mFinalStatus != OK) {
- LOG(VERBOSE) << "EOS reached, done prefetching for now";
+ LOGV("EOS reached, done prefetching for now");
mFetching = false;
}
@@ -268,7 +268,7 @@
if (mFetching || keepAlive) {
if (keepAlive) {
- LOG(INFO) << "Keep alive";
+ LOGI("Keep alive");
}
fetchInternal();
@@ -276,7 +276,7 @@
mLastFetchTimeUs = ALooper::GetNowUs();
if (mFetching && mCache->totalSize() >= kHighWaterThreshold) {
- LOG(INFO) << "Cache full, done prefetching for now";
+ LOGI("Cache full, done prefetching for now");
mFetching = false;
}
} else {
@@ -289,7 +289,7 @@
}
void NuCachedSource2::onRead(const sp<AMessage> &msg) {
- LOG(VERBOSE) << "onRead";
+ LOGV("onRead");
int64_t offset;
CHECK(msg->findInt64("offset", &offset));
@@ -339,14 +339,14 @@
size_t actualBytes = mCache->releaseFromStart(maxBytes);
mCacheOffset += actualBytes;
- LOG(INFO) << "restarting prefetcher, totalSize = " << mCache->totalSize();
+ LOGI("restarting prefetcher, totalSize = %d", mCache->totalSize());
mFetching = true;
}
ssize_t NuCachedSource2::readAt(off_t offset, void *data, size_t size) {
Mutex::Autolock autoSerializer(mSerializer);
- LOG(VERBOSE) << "readAt offset " << offset << " size " << size;
+ LOGV("readAt offset %ld, size %d", offset, size);
Mutex::Autolock autoLock(mLock);
@@ -406,7 +406,7 @@
}
ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) {
- LOG(VERBOSE) << "readInternal offset " << offset << " size " << size;
+ LOGV("readInternal offset %ld size %d", offset, size);
Mutex::Autolock autoLock(mLock);
@@ -442,7 +442,7 @@
return size;
}
- LOG(VERBOSE) << "deferring read";
+ LOGV("deferring read");
return -EAGAIN;
}
@@ -455,7 +455,7 @@
return OK;
}
- LOG(INFO) << "new range: offset= " << offset;
+ LOGI("new range: offset= %ld", offset);
mCacheOffset = offset;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4e79575..1b2be41 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1821,7 +1821,7 @@
case OMX_EventError:
{
- LOGE("ERROR(0x%08lx, %ld)", data1, data2);
+ CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
setState(ERROR);
break;
diff --git a/media/libstagefright/ThreadedSource.cpp b/media/libstagefright/ThreadedSource.cpp
index 5add2a5..38c6e2d 100644
--- a/media/libstagefright/ThreadedSource.cpp
+++ b/media/libstagefright/ThreadedSource.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#define LOG_TAG "ThreadedSource"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
#include "include/ThreadedSource.h"
#include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 7483d60..3c0b736 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -232,6 +232,53 @@
}
}
+MediaBuffer *AVCDecoder::drainOutputBuffer() {
+ int32_t index;
+ int32_t Release;
+ AVCFrameIO Output;
+ Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
+ AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
+
+ if (status != AVCDEC_SUCCESS) {
+ LOGV("PVAVCDecGetOutput returned error %d", status);
+ return NULL;
+ }
+
+ CHECK(index >= 0);
+ CHECK(index < (int32_t)mFrames.size());
+
+ MediaBuffer *mbuf = mFrames.editItemAt(index);
+
+ bool skipFrame = false;
+
+ if (mTargetTimeUs >= 0) {
+ int64_t timeUs;
+ CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(timeUs <= mTargetTimeUs);
+
+ if (timeUs < mTargetTimeUs) {
+ // We're still waiting for the frame with the matching
+ // timestamp and we won't return the current one.
+ skipFrame = true;
+
+ LOGV("skipping frame at %lld us", timeUs);
+ } else {
+ LOGV("found target frame at %lld us", timeUs);
+
+ mTargetTimeUs = -1;
+ }
+ }
+
+ if (!skipFrame) {
+ mbuf->set_range(0, mbuf->size());
+ mbuf->add_ref();
+
+ return mbuf;
+ }
+
+ return new MediaBuffer(0);
+}
+
status_t AVCDecoder::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
@@ -279,7 +326,8 @@
seekOptions.clearSeekTo();
if (err != OK) {
- return err;
+ *out = drainOutputBuffer();
+ return (*out == NULL) ? err : (status_t)OK;
}
if (mInputBuffer->range_length() > 0) {
@@ -415,51 +463,12 @@
fragSize);
if (res == AVCDEC_PICTURE_OUTPUT_READY) {
- int32_t index;
- int32_t Release;
- AVCFrameIO Output;
- Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
-
- AVCDec_Status status =
- PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
-
- if (status != AVCDEC_SUCCESS) {
- LOGV("PVAVCDecGetOutput returned error %d", status);
+ MediaBuffer *mbuf = drainOutputBuffer();
+ if (mbuf == NULL) {
break;
}
- CHECK(index >= 0);
- CHECK(index < (int32_t)mFrames.size());
-
- MediaBuffer *mbuf = mFrames.editItemAt(index);
-
- bool skipFrame = false;
-
- if (mTargetTimeUs >= 0) {
- int64_t timeUs;
- CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
- CHECK(timeUs <= mTargetTimeUs);
-
- if (timeUs < mTargetTimeUs) {
- // We're still waiting for the frame with the matching
- // timestamp and we won't return the current one.
- skipFrame = true;
-
- LOGV("skipping frame at %lld us", timeUs);
- } else {
- LOGV("found target frame at %lld us", timeUs);
-
- mTargetTimeUs = -1;
- }
- }
-
- if (!skipFrame) {
- *out = mbuf;
- (*out)->set_range(0, (*out)->size());
- (*out)->add_ref();
- } else {
- *out = new MediaBuffer(0);
- }
+ *out = mbuf;
// Do _not_ release input buffer yet.
@@ -496,6 +505,7 @@
case AVC_NALTYPE_AUD:
case AVC_NALTYPE_FILL:
+ case AVC_NALTYPE_EOSEQ:
{
*out = new MediaBuffer(0);
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
deleted file mode 100644
index 16f8b22..0000000
--- a/media/libstagefright/foundation/ADebug.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.
- */
-
-#include "ADebug.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef ANDROID
-#include <cutils/log.h>
-#endif
-
-namespace android {
-
-Logger::Logger(LogType type)
- : mLogType(type) {
- switch (mLogType) {
- case VERBOSE:
- mMessage = "V ";
- break;
- case INFO:
- mMessage = "I ";
- break;
- case WARNING:
- mMessage = "W ";
- break;
- case ERROR:
- mMessage = "E ";
- break;
- case FATAL:
- mMessage = "F ";
- break;
-
- default:
- break;
- }
-}
-
-Logger::~Logger() {
- if (mLogType == VERBOSE) {
- return;
- }
-
- mMessage.append("\n");
-
-#if defined(ANDROID) && 1
- LOG_PRI(ANDROID_LOG_INFO, "ADebug", "%s", mMessage.c_str());
-#else
- fprintf(stderr, mMessage.c_str());
- fflush(stderr);
-#endif
-
- if (mLogType == FATAL) {
- abort();
- }
-}
-
-const char *LeafName(const char *s) {
- const char *lastSlash = strrchr(s, '/');
- return lastSlash != NULL ? lastSlash + 1 : s;
-}
-
-} // namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 65f7593..7683113 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -74,7 +74,7 @@
ssize_t index = mHandlers.indexOfKey(msg->target());
if (index < 0) {
- LOG(WARNING) << "failed to post message. Target handler not registered.";
+ LOGW("failed to post message. Target handler not registered.");
return;
}
@@ -83,8 +83,8 @@
sp<ALooper> looper = info.mLooper.promote();
if (looper == NULL) {
- LOG(WARNING) << "failed to post message. "
- "Target handler still registered, but object gone.";
+ LOGW("failed to post message. "
+ "Target handler still registered, but object gone.");
mHandlers.removeItemsAt(index);
return;
@@ -102,8 +102,7 @@
ssize_t index = mHandlers.indexOfKey(msg->target());
if (index < 0) {
- LOG(WARNING) << "failed to deliver message. "
- << "Target handler not registered.";
+ LOGW("failed to deliver message. Target handler not registered.");
return;
}
@@ -111,8 +110,8 @@
handler = info.mHandler.promote();
if (handler == NULL) {
- LOG(WARNING) << "failed to deliver message. "
- "Target handler registered, but object gone.";
+ LOGW("failed to deliver message. "
+ "Target handler registered, but object gone.");
mHandlers.removeItemsAt(index);
return;
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index f6a8a52..ffa7db0 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -5,7 +5,6 @@
AAtomizer.cpp \
ABitReader.cpp \
ABuffer.cpp \
- ADebug.cpp \
AHandler.cpp \
ALooper.cpp \
ALooperRoster.cpp \
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/libstagefright/foundation/hexdump.cpp
index 093b587..9f6bf9e 100644
--- a/media/libstagefright/foundation/hexdump.cpp
+++ b/media/libstagefright/foundation/hexdump.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hexdump"
+#include <utils/Log.h>
+
#include "hexdump.h"
#include "ADebug.h"
@@ -63,7 +67,7 @@
}
}
- LOG(INFO) << line;
+ LOGI("%s", line.c_str());
offset += 16;
}
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
index 898c90a..eb3b142 100644
--- a/media/libstagefright/include/AVCDecoder.h
+++ b/media/libstagefright/include/AVCDecoder.h
@@ -82,6 +82,8 @@
void releaseFrames();
+ MediaBuffer *drainOutputBuffer();
+
AVCDecoder(const AVCDecoder &);
AVCDecoder &operator=(const AVCDecoder &);
};
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 72de8d7..9952783 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ATSParser"
+#include <utils/Log.h>
+
#include "ATSParser.h"
#include "AnotherPacketSource.h"
@@ -31,6 +35,10 @@
namespace android {
+// I want the expression "y" evaluated even if verbose logging is off.
+#define MY_LOGV(x, y) \
+ do { unsigned tmp = y; LOGV(x, tmp); } while (0)
+
static const size_t kTSPacketSize = 188;
struct ATSParser::Program : public RefBase {
@@ -115,36 +123,33 @@
void ATSParser::Program::parseProgramMap(ABitReader *br) {
unsigned table_id = br->getBits(8);
- LOG(VERBOSE) << " table_id = " << table_id;
+ LOGV(" table_id = %u", table_id);
CHECK_EQ(table_id, 0x02u);
- unsigned section_syntax_indictor = br->getBits(1);
- LOG(VERBOSE) << " section_syntax_indictor = " << section_syntax_indictor;
- CHECK_EQ(section_syntax_indictor, 1u);
+ unsigned section_syntax_indicator = br->getBits(1);
+ LOGV(" section_syntax_indicator = %u", section_syntax_indicator);
+ CHECK_EQ(section_syntax_indicator, 1u);
CHECK_EQ(br->getBits(1), 0u);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
+ MY_LOGV(" reserved = %u", br->getBits(2));
unsigned section_length = br->getBits(12);
- LOG(VERBOSE) << " section_length = " << section_length;
+ LOGV(" section_length = %u", section_length);
CHECK((section_length & 0xc00) == 0);
CHECK_LE(section_length, 1021u);
- LOG(VERBOSE) << " program_number = " << br->getBits(16);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
- LOG(VERBOSE) << " version_number = " << br->getBits(5);
- LOG(VERBOSE) << " current_next_indicator = " << br->getBits(1);
- LOG(VERBOSE) << " section_number = " << br->getBits(8);
- LOG(VERBOSE) << " last_section_number = " << br->getBits(8);
- LOG(VERBOSE) << " reserved = " << br->getBits(3);
-
- LOG(VERBOSE) << " PCR_PID = "
- << StringPrintf("0x%04x", br->getBits(13));
-
- LOG(VERBOSE) << " reserved = " << br->getBits(4);
+ MY_LOGV(" program_number = %u", br->getBits(16));
+ MY_LOGV(" reserved = %u", br->getBits(2));
+ MY_LOGV(" version_number = %u", br->getBits(5));
+ MY_LOGV(" current_next_indicator = %u", br->getBits(1));
+ MY_LOGV(" section_number = %u", br->getBits(8));
+ MY_LOGV(" last_section_number = %u", br->getBits(8));
+ MY_LOGV(" reserved = %u", br->getBits(3));
+ MY_LOGV(" PCR_PID = 0x%04x", br->getBits(13));
+ MY_LOGV(" reserved = %u", br->getBits(4));
unsigned program_info_length = br->getBits(12);
- LOG(VERBOSE) << " program_info_length = " << program_info_length;
+ LOGV(" program_info_length = %u", program_info_length);
CHECK((program_info_length & 0xc00) == 0);
br->skipBits(program_info_length * 8); // skip descriptors
@@ -158,19 +163,17 @@
CHECK_GE(infoBytesRemaining, 5u);
unsigned streamType = br->getBits(8);
- LOG(VERBOSE) << " stream_type = "
- << StringPrintf("0x%02x", streamType);
+ LOGV(" stream_type = 0x%02x", streamType);
- LOG(VERBOSE) << " reserved = " << br->getBits(3);
+ MY_LOGV(" reserved = %u", br->getBits(3));
unsigned elementaryPID = br->getBits(13);
- LOG(VERBOSE) << " elementary_PID = "
- << StringPrintf("0x%04x", elementaryPID);
+ LOGV(" elementary_PID = 0x%04x", elementaryPID);
- LOG(VERBOSE) << " reserved = " << br->getBits(4);
+ MY_LOGV(" reserved = %u", br->getBits(4));
unsigned ES_info_length = br->getBits(12);
- LOG(VERBOSE) << " ES_info_length = " << ES_info_length;
+ LOGV(" ES_info_length = %u", ES_info_length);
CHECK((ES_info_length & 0xc00) == 0);
CHECK_GE(infoBytesRemaining - 5, ES_info_length);
@@ -180,10 +183,10 @@
#else
unsigned info_bytes_remaining = ES_info_length;
while (info_bytes_remaining >= 2) {
- LOG(VERBOSE) << " tag = " << StringPrintf("0x%02x", br->getBits(8));
+ MY_LOGV(" tag = 0x%02x", br->getBits(8));
unsigned descLength = br->getBits(8);
- LOG(VERBOSE) << " len = " << descLength;
+ LOGV(" len = %u", descLength);
CHECK_GE(info_bytes_remaining, 2 + descLength);
@@ -209,7 +212,7 @@
CHECK_EQ(infoBytesRemaining, 0u);
- LOG(VERBOSE) << " CRC = " << StringPrintf("0x%08x", br->getBits(32));
+ MY_LOGV(" CRC = 0x%08x", br->getBits(32));
}
sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
@@ -255,7 +258,7 @@
}
size_t payloadSizeBits = br->numBitsLeft();
- CHECK_EQ(payloadSizeBits % 8, 0u);
+ CHECK((payloadSizeBits % 8) == 0);
CHECK_LE(mBuffer->size() + payloadSizeBits / 8, mBuffer->capacity());
@@ -266,16 +269,15 @@
void ATSParser::Stream::parsePES(ABitReader *br) {
unsigned packet_startcode_prefix = br->getBits(24);
- LOG(VERBOSE) << "packet_startcode_prefix = "
- << StringPrintf("0x%08x", packet_startcode_prefix);
+ LOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
CHECK_EQ(packet_startcode_prefix, 0x000001u);
unsigned stream_id = br->getBits(8);
- LOG(VERBOSE) << "stream_id = " << StringPrintf("0x%02x", stream_id);
+ LOGV("stream_id = 0x%02x", stream_id);
unsigned PES_packet_length = br->getBits(16);
- LOG(VERBOSE) << "PES_packet_length = " << PES_packet_length;
+ LOGV("PES_packet_length = %u", PES_packet_length);
if (stream_id != 0xbc // program_stream_map
&& stream_id != 0xbe // padding_stream
@@ -287,33 +289,32 @@
&& stream_id != 0xf8) { // H.222.1 type E
CHECK_EQ(br->getBits(2), 2u);
- LOG(VERBOSE) << "PES_scrambling_control = " << br->getBits(2);
- LOG(VERBOSE) << "PES_priority = " << br->getBits(1);
- LOG(VERBOSE) << "data_alignment_indicator = " << br->getBits(1);
- LOG(VERBOSE) << "copyright = " << br->getBits(1);
- LOG(VERBOSE) << "original_or_copy = " << br->getBits(1);
+ MY_LOGV("PES_scrambling_control = %u", br->getBits(2));
+ MY_LOGV("PES_priority = %u", br->getBits(1));
+ MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
+ MY_LOGV("copyright = %u", br->getBits(1));
+ MY_LOGV("original_or_copy = %u", br->getBits(1));
unsigned PTS_DTS_flags = br->getBits(2);
- LOG(VERBOSE) << "PTS_DTS_flags = " << PTS_DTS_flags;
+ LOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
unsigned ESCR_flag = br->getBits(1);
- LOG(VERBOSE) << "ESCR_flag = " << ESCR_flag;
+ LOGV("ESCR_flag = %u", ESCR_flag);
unsigned ES_rate_flag = br->getBits(1);
- LOG(VERBOSE) << "ES_rate_flag = " << ES_rate_flag;
+ LOGV("ES_rate_flag = %u", ES_rate_flag);
unsigned DSM_trick_mode_flag = br->getBits(1);
- LOG(VERBOSE) << "DSM_trick_mode_flag = " << DSM_trick_mode_flag;
+ LOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
unsigned additional_copy_info_flag = br->getBits(1);
- LOG(VERBOSE) << "additional_copy_info_flag = "
- << additional_copy_info_flag;
+ LOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
- LOG(VERBOSE) << "PES_CRC_flag = " << br->getBits(1);
- LOG(VERBOSE) << "PES_extension_flag = " << br->getBits(1);
+ MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
+ MY_LOGV("PES_extension_flag = %u", br->getBits(1));
unsigned PES_header_data_length = br->getBits(8);
- LOG(VERBOSE) << "PES_header_data_length = " << PES_header_data_length;
+ LOGV("PES_header_data_length = %u", PES_header_data_length);
unsigned optional_bytes_remaining = PES_header_data_length;
@@ -331,8 +332,8 @@
PTS |= br->getBits(15);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "PTS = " << PTS;
- // LOG(INFO) << "PTS = " << PTS / 90000.0f << " secs";
+ LOGV("PTS = %llu", PTS);
+ // LOGI("PTS = %.2f secs", PTS / 90000.0f);
optional_bytes_remaining -= 5;
@@ -348,7 +349,7 @@
DTS |= br->getBits(15);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "DTS = " << DTS;
+ LOGV("DTS = %llu", DTS);
optional_bytes_remaining -= 5;
}
@@ -366,8 +367,8 @@
ESCR |= br->getBits(15);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "ESCR = " << ESCR;
- LOG(VERBOSE) << "ESCR_extension = " << br->getBits(9);
+ LOGV("ESCR = %llu", ESCR);
+ MY_LOGV("ESCR_extension = %u", br->getBits(9));
CHECK_EQ(br->getBits(1), 1u);
@@ -378,7 +379,7 @@
CHECK_GE(optional_bytes_remaining, 3u);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "ES_rate = " << br->getBits(22);
+ MY_LOGV("ES_rate = %u", br->getBits(22));
CHECK_EQ(br->getBits(1), 1u);
optional_bytes_remaining -= 3;
@@ -405,8 +406,7 @@
size_t payloadSizeBits = br->numBitsLeft();
CHECK((payloadSizeBits % 8) == 0);
- LOG(VERBOSE) << "There's " << (payloadSizeBits / 8)
- << " bytes of payload.";
+ LOGV("There's %d bytes of payload.", payloadSizeBits / 8);
}
} else if (stream_id == 0xbe) { // padding_stream
CHECK_NE(PES_packet_length, 0u);
@@ -422,9 +422,7 @@
return;
}
- LOG(VERBOSE) << "flushing stream "
- << StringPrintf("0x%04x", mElementaryPID)
- << " size = " << mBuffer->size();
+ LOGV("flushing stream 0x%04x size = %d", mElementaryPID, mBuffer->size());
ABitReader br(mBuffer->data(), mBuffer->size());
parsePES(&br);
@@ -493,7 +491,7 @@
CHECK(picParamSet != NULL);
buffer->setRange(stopOffset, size - stopOffset);
- LOG(INFO) << "buffer has " << buffer->size() << " bytes left.";
+ LOGI("buffer has %d bytes left.", buffer->size());
size_t csdSize =
1 + 3 + 1 + 1
@@ -617,15 +615,15 @@
CHECK_EQ(br.getBits(2), 0u);
br.getBits(1); // protection_absent
unsigned profile = br.getBits(2);
- LOG(INFO) << "profile = " << profile;
+ LOGI("profile = %u", profile);
CHECK_NE(profile, 3u);
unsigned sampling_freq_index = br.getBits(4);
br.getBits(1); // private_bit
unsigned channel_configuration = br.getBits(3);
CHECK_NE(channel_configuration, 0u);
- LOG(INFO) << "sampling_freq_index = " << sampling_freq_index;
- LOG(INFO) << "channel_configuration = " << channel_configuration;
+ LOGI("sampling_freq_index = %u", sampling_freq_index);
+ LOGI("channel_configuration = %u", channel_configuration);
CHECK_LE(sampling_freq_index, 11u);
static const int32_t kSamplingFreq[] = {
@@ -671,8 +669,7 @@
void ATSParser::Stream::onPayloadData(
unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
const uint8_t *data, size_t size) {
- LOG(VERBOSE) << "onPayloadData mStreamType="
- << StringPrintf("0x%02x", mStreamType);
+ LOGV("onPayloadData mStreamType=0x%02x", mStreamType);
sp<ABuffer> buffer;
@@ -710,8 +707,8 @@
sp<ABuffer> csd =
FindMPEG2ADTSConfig(buffer, &sampleRate, &channelCount);
- LOG(INFO) << "sampleRate = " << sampleRate;
- LOG(INFO) << "channelCount = " << channelCount;
+ LOGI("sampleRate = %d", sampleRate);
+ LOGI("channelCount = %d", channelCount);
meta->setInt32(kKeySampleRate, sampleRate);
meta->setInt32(kKeyChannelCount, channelCount);
@@ -719,7 +716,7 @@
meta->setData(kKeyESDS, 0, csd->data(), csd->size());
}
- LOG(INFO) << "created source!";
+ LOGI("created source!");
mSource = new AnotherPacketSource(meta);
// fall through
@@ -777,12 +774,7 @@
CHECK_LE(scan, buffer->size());
- LOG(VERBOSE)
- << "found aac raw data block at ["
- << StringPrintf("0x%08x", offset)
- << " ; "
- << StringPrintf("0x%08x", scan)
- << ")";
+ LOGV("found aac raw data block at [0x%08x ; 0x%08x)", offset, scan);
memmove(&buffer->data()[dstOffset], &buffer->data()[offset],
scan - offset);
@@ -825,50 +817,48 @@
void ATSParser::parseProgramAssociationTable(ABitReader *br) {
unsigned table_id = br->getBits(8);
- LOG(VERBOSE) << " table_id = " << table_id;
+ LOGV(" table_id = %u", table_id);
CHECK_EQ(table_id, 0x00u);
unsigned section_syntax_indictor = br->getBits(1);
- LOG(VERBOSE) << " section_syntax_indictor = " << section_syntax_indictor;
+ LOGV(" section_syntax_indictor = %u", section_syntax_indictor);
CHECK_EQ(section_syntax_indictor, 1u);
CHECK_EQ(br->getBits(1), 0u);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
+ MY_LOGV(" reserved = %u", br->getBits(2));
unsigned section_length = br->getBits(12);
- LOG(VERBOSE) << " section_length = " << section_length;
+ LOGV(" section_length = %u", section_length);
CHECK((section_length & 0xc00) == 0);
- LOG(VERBOSE) << " transport_stream_id = " << br->getBits(16);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
- LOG(VERBOSE) << " version_number = " << br->getBits(5);
- LOG(VERBOSE) << " current_next_indicator = " << br->getBits(1);
- LOG(VERBOSE) << " section_number = " << br->getBits(8);
- LOG(VERBOSE) << " last_section_number = " << br->getBits(8);
+ MY_LOGV(" transport_stream_id = %u", br->getBits(16));
+ MY_LOGV(" reserved = %u", br->getBits(2));
+ MY_LOGV(" version_number = %u", br->getBits(5));
+ MY_LOGV(" current_next_indicator = %u", br->getBits(1));
+ MY_LOGV(" section_number = %u", br->getBits(8));
+ MY_LOGV(" last_section_number = %u", br->getBits(8));
size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
CHECK_EQ((numProgramBytes % 4), 0u);
for (size_t i = 0; i < numProgramBytes / 4; ++i) {
unsigned program_number = br->getBits(16);
- LOG(VERBOSE) << " program_number = " << program_number;
+ LOGV(" program_number = %u", program_number);
- LOG(VERBOSE) << " reserved = " << br->getBits(3);
+ MY_LOGV(" reserved = %u", br->getBits(3));
if (program_number == 0) {
- LOG(VERBOSE) << " network_PID = "
- << StringPrintf("0x%04x", br->getBits(13));
+ MY_LOGV(" network_PID = 0x%04x", br->getBits(13));
} else {
unsigned programMapPID = br->getBits(13);
- LOG(VERBOSE) << " program_map_PID = "
- << StringPrintf("0x%04x", programMapPID);
+ LOGV(" program_map_PID = 0x%04x", programMapPID);
mPrograms.push(new Program(programMapPID));
}
}
- LOG(VERBOSE) << " CRC = " << StringPrintf("0x%08x", br->getBits(32));
+ MY_LOGV(" CRC = 0x%08x", br->getBits(32));
}
void ATSParser::parsePID(
@@ -893,8 +883,7 @@
}
if (!handled) {
- LOG(WARNING) << "PID " << StringPrintf("0x%04x", PID)
- << " not handled.";
+ LOGV("PID 0x%04x not handled.", PID);
}
}
@@ -906,28 +895,27 @@
}
void ATSParser::parseTS(ABitReader *br) {
- LOG(VERBOSE) << "---";
+ LOGV("---");
unsigned sync_byte = br->getBits(8);
CHECK_EQ(sync_byte, 0x47u);
- LOG(VERBOSE) << "transport_error_indicator = " << br->getBits(1);
+ MY_LOGV("transport_error_indicator = %u", br->getBits(1));
unsigned payload_unit_start_indicator = br->getBits(1);
- LOG(VERBOSE) << "payload_unit_start_indicator = "
- << payload_unit_start_indicator;
+ LOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
- LOG(VERBOSE) << "transport_priority = " << br->getBits(1);
+ MY_LOGV("transport_priority = %u", br->getBits(1));
unsigned PID = br->getBits(13);
- LOG(VERBOSE) << "PID = " << StringPrintf("0x%04x", PID);
+ LOGV("PID = 0x%04x", PID);
- LOG(VERBOSE) << "transport_scrambling_control = " << br->getBits(2);
+ MY_LOGV("transport_scrambling_control = %u", br->getBits(2));
unsigned adaptation_field_control = br->getBits(2);
- LOG(VERBOSE) << "adaptation_field_control = " << adaptation_field_control;
+ LOGV("adaptation_field_control = %u", adaptation_field_control);
- LOG(VERBOSE) << "continuity_counter = " << br->getBits(4);
+ MY_LOGV("continuity_counter = %u", br->getBits(4));
if (adaptation_field_control == 2 || adaptation_field_control == 3) {
parseAdaptationField(br);
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index fcf506d..4f28855 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -286,7 +286,7 @@
return OK;
}
- sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024, "OMXHarness");
+ sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
IOMX::node_id node;
status_t err =
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
index 154ba31..b1f6e9a 100644
--- a/media/libstagefright/rtsp/AAMRAssembler.cpp
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AAMRAssembler"
+#include <utils/Log.h>
+
#include "AAMRAssembler.h"
#include "ARTPSource.h"
@@ -119,9 +123,7 @@
mNextExpectedSeqNoValid = true;
mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
} else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if VERBOSE
- LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+ LOGV("Not the sequence number I expected");
return WRONG_SEQUENCE_NUMBER;
}
@@ -132,7 +134,7 @@
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "AMR packet too short.";
+ LOGV("AMR packet too short.");
return MALFORMED_PACKET;
}
@@ -150,7 +152,7 @@
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "Unable to parse TOC.";
+ LOGV("Unable to parse TOC.");
return MALFORMED_PACKET;
}
@@ -164,7 +166,7 @@
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "Illegal TOC entry.";
+ LOGV("Illegal TOC entry.");
return MALFORMED_PACKET;
}
@@ -191,7 +193,7 @@
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "AMR packet too short.";
+ LOGV("AMR packet too short.");
return MALFORMED_PACKET;
}
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index 6b1e292..11c6ae7 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AAVCAssembler"
+#include <utils/Log.h>
+
#include "AAVCAssembler.h"
#include "ARTPSource.h"
@@ -25,8 +29,6 @@
#include <stdint.h>
-#define BE_VERBOSE 0
-
namespace android {
// static
@@ -70,9 +72,7 @@
mNextExpectedSeqNoValid = true;
mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
} else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+ LOGV("Not the sequence number I expected");
return WRONG_SEQUENCE_NUMBER;
}
@@ -83,7 +83,7 @@
if (size < 1 || (data[0] & 0x80)) {
// Corrupt.
- LOG(ERROR) << "Ignoring corrupt buffer.";
+ LOGV("Ignoring corrupt buffer.");
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -107,7 +107,7 @@
return success ? OK : MALFORMED_PACKET;
} else {
- LOG(ERROR) << "Ignoring unsupported buffer (nalType=" << nalType << ")";
+ LOGV("Ignoring unsupported buffer (nalType=%d)", nalType);
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -117,8 +117,8 @@
}
void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "addSingleNALUnit of size " << buffer->size();
+ LOGV("addSingleNALUnit of size %d", buffer->size());
+#if !LOG_NDEBUG
hexdump(buffer->data(), buffer->size());
#endif
@@ -138,7 +138,7 @@
size_t size = buffer->size();
if (size < 3) {
- LOG(ERROR) << "Discarding too small STAP-A packet.";
+ LOGV("Discarding too small STAP-A packet.");
return false;
}
@@ -148,7 +148,7 @@
size_t nalSize = (data[0] << 8) | data[1];
if (size < nalSize + 2) {
- LOG(ERROR) << "Discarding malformed STAP-A packet.";
+ LOGV("Discarding malformed STAP-A packet.");
return false;
}
@@ -164,7 +164,7 @@
}
if (size != 0) {
- LOG(WARNING) << "Unexpected padding at end of STAP-A packet.";
+ LOGV("Unexpected padding at end of STAP-A packet.");
}
return true;
@@ -184,7 +184,7 @@
CHECK((indicator & 0x1f) == 28);
if (size < 2) {
- LOG(ERROR) << "Ignoring malformed FU buffer (size = " << size << ")";
+ LOGV("Ignoring malformed FU buffer (size = %d)", size);
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -194,9 +194,7 @@
if (!(data[1] & 0x80)) {
// Start bit not set on the first buffer.
-#if BE_VERBOSE
- LOG(ERROR) << "Start bit not set on first buffer";
-#endif
+ LOGV("Start bit not set on first buffer");
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -214,17 +212,13 @@
if (data[1] & 0x40) {
// Huh? End bit also set on the first buffer.
-#if BE_VERBOSE
- LOG(WARNING) << "Grrr. This isn't fragmented at all.";
-#endif
+ LOGV("Grrr. This isn't fragmented at all.");
complete = true;
} else {
List<sp<ABuffer> >::iterator it = ++queue->begin();
while (it != queue->end()) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "sequence length " << totalCount;
-#endif
+ LOGV("sequence length %d", totalCount);
const sp<ABuffer> &buffer = *it;
@@ -232,11 +226,8 @@
size_t size = buffer->size();
if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "sequence not complete, expected seqNo "
- << expectedSeqNo << ", got "
- << (uint32_t)buffer->int32Data();
-#endif
+ LOGV("sequence not complete, expected seqNo %d, got %d",
+ expectedSeqNo, (uint32_t)buffer->int32Data());
return WRONG_SEQUENCE_NUMBER;
}
@@ -245,7 +236,7 @@
|| data[0] != indicator
|| (data[1] & 0x1f) != nalType
|| (data[1] & 0x80)) {
- LOG(ERROR) << "Ignoring malformed FU buffer.\n";
+ LOGV("Ignoring malformed FU buffer.");
// Delete the whole start of the FU.
@@ -296,8 +287,8 @@
for (size_t i = 0; i < totalCount; ++i) {
const sp<ABuffer> &buffer = *it;
-#if BE_VERBOSE
- LOG(VERBOSE) << "piece #" << (i + 1) << "/" << totalCount;
+ LOGV("piece #%d/%d", i + 1, totalCount);
+#if !LOG_NDEBUG
hexdump(buffer->data(), buffer->size());
#endif
@@ -311,9 +302,7 @@
addSingleNALUnit(unit);
-#if BE_VERBOSE
- LOG(VERBOSE) << "successfully assembled a NAL unit from fragments.";
-#endif
+ LOGV("successfully assembled a NAL unit from fragments.");
return OK;
}
@@ -321,9 +310,7 @@
void AAVCAssembler::submitAccessUnit() {
CHECK(!mNALUnits.empty());
-#if BE_VERBOSE
- LOG(VERBOSE) << "Access unit complete (" << mNALUnits.size() << " nal units)";
-#endif
+ LOGV("Access unit complete (%d nal units)", mNALUnits.size());
size_t totalSize = 0;
for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
@@ -373,7 +360,7 @@
void AAVCAssembler::packetLost() {
CHECK(mNextExpectedSeqNoValid);
- LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
+ LOGV("packetLost (expected %d)", mNextExpectedSeqNo);
++mNextExpectedSeqNo;
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index f68a35b..13988cd 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AMPEG4ElementaryAssembler"
+#include <utils/Log.h>
+
#include "AMPEG4ElementaryAssembler.h"
#include "ARTPSource.h"
@@ -28,8 +32,6 @@
#include <ctype.h>
#include <stdint.h>
-#define BE_VERBOSE 0
-
namespace android {
static bool GetAttribute(const char *s, const char *key, AString *value) {
@@ -201,9 +203,7 @@
mNextExpectedSeqNoValid = true;
mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
} else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+ LOGV("Not the sequence number I expected");
return WRONG_SEQUENCE_NUMBER;
}
@@ -336,9 +336,7 @@
void AMPEG4ElementaryAssembler::submitAccessUnit() {
CHECK(!mPackets.empty());
-#if BE_VERBOSE
- LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " nal units)";
-#endif
+ LOGV("Access unit complete (%d nal units)", mPackets.size());
size_t totalSize = 0;
for (List<sp<ABuffer> >::iterator it = mPackets.begin();
@@ -385,7 +383,7 @@
void AMPEG4ElementaryAssembler::packetLost() {
CHECK(mNextExpectedSeqNoValid);
- LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
+ LOGV("packetLost (expected %d)", mNextExpectedSeqNo);
++mNextExpectedSeqNo;
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index b3e86eb..78754e6 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "APacketSource"
+#include <utils/Log.h>
+
#include "APacketSource.h"
#include "ASessionDescription.h"
@@ -188,7 +192,7 @@
if (i == 0) {
FindAVCDimensions(nal, width, height);
- LOG(INFO) << "dimensions " << *width << "x" << *height;
+ LOGI("dimensions %dx%d", *width, *height);
}
}
@@ -412,7 +416,7 @@
*width = video_object_layer_width;
*height = video_object_layer_height;
- LOG(INFO) << "VOL dimensions = " << *width << "x" << *height;
+ LOGI("VOL dimensions = %dx%d", *width, *height);
return true;
}
@@ -711,7 +715,7 @@
void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
int32_t damaged;
if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
- LOG(VERBOSE) << "discarding damaged AU";
+ LOGV("discarding damaged AU");
return;
}
@@ -765,8 +769,9 @@
CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
if (lastTimeUs < firstTimeUs) {
- LOG(ERROR) << "Huh? Time moving backwards? "
- << firstTimeUs << " > " << lastTimeUs;
+ LOGE("Huh? Time moving backwards? %lld > %lld",
+ firstTimeUs, lastTimeUs);
+
return 0;
}
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 10c9e02..ded3b24 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPConnection"
+#include <utils/Log.h>
+
#include "ARTPConnection.h"
#include "ARTPSource.h"
@@ -319,7 +323,7 @@
}
if (buffer->size() > 0) {
- LOG(VERBOSE) << "Sending RR...";
+ LOGV("Sending RR...");
ssize_t n = sendto(
s->mRTCPSocket, buffer->data(), buffer->size(), 0,
@@ -356,7 +360,7 @@
buffer->setRange(0, nbytes);
- // LOG(INFO) << "received " << buffer->size() << " bytes.";
+ // LOGI("received %d bytes.", buffer->size());
status_t err;
if (receiveRTP) {
@@ -521,9 +525,8 @@
default:
{
- LOG(WARNING) << "Unknown RTCP packet type "
- << (unsigned)data[1]
- << " of size " << headerLength;
+ LOGW("Unknown RTCP packet type %u of size %d",
+ (unsigned)data[1], headerLength);
break;
}
}
@@ -567,10 +570,10 @@
uint32_t rtpTime = u32at(&data[16]);
#if 0
- LOG(INFO) << StringPrintf(
- "XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
- id,
- rtpTime, (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
+ LOGI("XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
+ id,
+ rtpTime,
+ (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
#endif
sp<ARTPSource> source = findSource(s, id);
diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp
index 8ce93b7..39c6619 100644
--- a/media/libstagefright/rtsp/ARTPSession.cpp
+++ b/media/libstagefright/rtsp/ARTPSession.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPSession"
+#include <utils/Log.h>
+
#include "ARTPSession.h"
#include <media/stagefright/foundation/ABuffer.h>
@@ -51,24 +55,24 @@
if (!mDesc->findAttribute(i, "c=", &connection)) {
// No per-stream connection information, try global fallback.
if (!mDesc->findAttribute(0, "c=", &connection)) {
- LOG(ERROR) << "Unable to find connection attribtue.";
+ LOGE("Unable to find connection attribute.");
return mInitCheck;
}
}
if (!(connection == "IN IP4 127.0.0.1")) {
- LOG(ERROR) << "We only support localhost connections for now.";
+ LOGE("We only support localhost connections for now.");
return mInitCheck;
}
unsigned port;
if (!validateMediaFormat(i, &port) || (port & 1) != 0) {
- LOG(ERROR) << "Invalid media format.";
+ LOGE("Invalid media format.");
return mInitCheck;
}
sp<APacketSource> source = new APacketSource(mDesc, i);
if (source->initCheck() != OK) {
- LOG(ERROR) << "Unsupported format.";
+ LOGE("Unsupported format.");
return mInitCheck;
}
@@ -157,9 +161,8 @@
printf("access unit complete size=%d\tntp-time=0x%016llx\n",
accessUnit->size(), ntpTime);
#else
- LOG(INFO) << "access unit complete, "
- << "size=" << accessUnit->size() << ", "
- << "ntp-time=" << ntpTime;
+ LOGI("access unit complete, size=%d, ntp-time=%llu",
+ accessUnit->size(), ntpTime);
hexdump(accessUnit->data(), accessUnit->size());
#endif
#endif
@@ -169,9 +172,8 @@
CHECK(!memcmp("\x00\x00\x00\x01", accessUnit->data(), 4));
unsigned x = accessUnit->data()[4];
- LOG(INFO) << "access unit complete: "
- << StringPrintf("nalType=0x%02x, nalRefIdc=0x%02x",
- x & 0x1f, (x & 0x60) >> 5);
+ LOGI("access unit complete: nalType=0x%02x, nalRefIdc=0x%02x",
+ x & 0x1f, (x & 0x60) >> 5);
#endif
accessUnit->meta()->setInt64("ntp-time", ntpTime);
@@ -181,7 +183,7 @@
int32_t damaged;
if (accessUnit->meta()->findInt32("damaged", &damaged)
&& damaged != 0) {
- LOG(INFO) << "ignoring damaged AU";
+ LOGI("ignoring damaged AU");
} else
#endif
{
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 9656ba2..2518264 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPSource"
+#include <utils/Log.h>
+
#include "ARTPSource.h"
#include "AAMRAssembler.h"
@@ -27,8 +31,6 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
-#define BE_VERBOSE 0
-
namespace android {
static const uint32_t kSourceID = 0xdeadbeef;
@@ -83,14 +85,10 @@
&& mAssembler != NULL) {
mAssembler->onPacketReceived(this);
}
-
- dump();
}
void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "timeUpdate";
-#endif
+ LOGV("timeUpdate");
mLastNTPTime = ntpTime;
mLastNTPTimeUpdateUs = ALooper::GetNowUs();
@@ -173,7 +171,7 @@
}
if (it != mQueue.end() && (uint32_t)(*it)->int32Data() == seqNum) {
- LOG(WARNING) << "Discarding duplicate buffer";
+ LOGW("Discarding duplicate buffer");
return false;
}
@@ -182,89 +180,6 @@
return true;
}
-void ARTPSource::dump() const {
- if ((mNumBuffersReceived % 128) != 0) {
- return;
- }
-
-#if 0
- if (mAssembler == NULL) {
- char tmp[20];
- sprintf(tmp, "0x%08x", mID);
-
- int32_t numMissing = 0;
-
- if (!mQueue.empty()) {
- List<sp<ABuffer> >::const_iterator it = mQueue.begin();
- uint32_t expectedSeqNum = (uint32_t)(*it)->int32Data();
- ++expectedSeqNum;
- ++it;
-
- for (; it != mQueue.end(); ++it) {
- uint32_t seqNum = (uint32_t)(*it)->int32Data();
- CHECK_GE(seqNum, expectedSeqNum);
-
- if (seqNum != expectedSeqNum) {
- numMissing += seqNum - expectedSeqNum;
- expectedSeqNum = seqNum;
- }
-
- ++expectedSeqNum;
- }
- }
-
- LOG(VERBOSE) << "[" << tmp << "] Missing " << numMissing
- << " / " << (mNumBuffersReceived + numMissing) << " packets. ("
- << (100.0 * numMissing / (mNumBuffersReceived + numMissing))
- << " %%)";
- }
-#endif
-
-#if 0
- AString out;
-
- out.append(tmp);
- out.append(" [");
-
- List<sp<ABuffer> >::const_iterator it = mQueue.begin();
- while (it != mQueue.end()) {
- uint32_t start = (uint32_t)(*it)->int32Data();
-
- out.append(start);
-
- ++it;
- uint32_t expected = start + 1;
-
- while (it != mQueue.end()) {
- uint32_t seqNum = (uint32_t)(*it)->int32Data();
-
- if (seqNum != expected) {
- if (expected > start + 1) {
- out.append("-");
- out.append(expected - 1);
- }
- out.append(", ");
- break;
- }
-
- ++it;
- ++expected;
- }
-
- if (it == mQueue.end()) {
- if (expected > start + 1) {
- out.append("-");
- out.append(expected - 1);
- }
- }
- }
-
- out.append("]");
-
- LOG(VERBOSE) << out;
-#endif
-}
-
uint64_t ARTPSource::RTP2NTP(uint32_t rtpTime) const {
CHECK_EQ(mNumTimes, 2u);
@@ -291,7 +206,7 @@
mLastFIRRequestUs = nowUs;
if (buffer->size() + 20 > buffer->capacity()) {
- LOG(WARNING) << "RTCP buffer too small to accomodate FIR.";
+ LOGW("RTCP buffer too small to accomodate FIR.");
return;
}
@@ -324,12 +239,12 @@
buffer->setRange(buffer->offset(), buffer->size() + 20);
- LOG(VERBOSE) << "Added FIR request.";
+ LOGV("Added FIR request.");
}
void ARTPSource::addReceiverReport(const sp<ABuffer> &buffer) {
if (buffer->size() + 32 > buffer->capacity()) {
- LOG(WARNING) << "RTCP buffer too small to accomodate RR.";
+ LOGW("RTCP buffer too small to accomodate RR.");
return;
}
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 252d6d6..e62c3f1 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -72,7 +72,6 @@
uint64_t RTP2NTP(uint32_t rtpTime) const;
bool queuePacket(const sp<ABuffer> &buffer);
- void dump() const;
DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
};
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index ce1ee0e..155fd96 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -1,3 +1,23 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPWriter"
+#include <utils/Log.h>
+
#include "ARTPWriter.h"
#include <fcntl.h>
@@ -249,7 +269,7 @@
status_t err = mSource->read(&mediaBuf);
if (err != OK) {
- LOG(INFO) << "reached EOS.";
+ LOGI("reached EOS.");
Mutex::Autolock autoLock(mLock);
mFlags |= kFlagEOS;
@@ -257,7 +277,7 @@
}
if (mediaBuf->range_length() > 0) {
- LOG(VERBOSE) << "read buffer of size " << mediaBuf->range_length();
+ LOGV("read buffer of size %d", mediaBuf->range_length());
if (mMode == H264) {
StripStartcode(mediaBuf);
@@ -500,7 +520,7 @@
sdp.append("a=fmtp:" PT_STR " octed-align\r\n");
}
- LOG(INFO) << sdp;
+ LOGI("%s", sdp.c_str());
}
void ARTPWriter::makeH264SPropParamSets(MediaBuffer *buffer) {
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index dcff64c..f928c06 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTSPConnection"
+#include <utils/Log.h>
+
#include "ARTSPConnection.h"
#include <media/stagefright/foundation/ABuffer.h>
@@ -41,7 +45,7 @@
ARTSPConnection::~ARTSPConnection() {
if (mSocket >= 0) {
- LOG(ERROR) << "Connection is still open, closing the socket.";
+ LOGE("Connection is still open, closing the socket.");
close(mSocket);
mSocket = -1;
}
@@ -184,7 +188,7 @@
AString host, path;
unsigned port;
if (!ParseURL(url.c_str(), &host, &port, &path)) {
- LOG(ERROR) << "Malformed rtsp url " << url;
+ LOGE("Malformed rtsp url %s", url.c_str());
reply->setInt32("result", ERROR_MALFORMED);
reply->post();
@@ -195,7 +199,7 @@
struct hostent *ent = gethostbyname(host.c_str());
if (ent == NULL) {
- LOG(ERROR) << "Unknown host " << host;
+ LOGE("Unknown host %s", host.c_str());
reply->setInt32("result", -ENOENT);
reply->post();
@@ -300,7 +304,7 @@
CHECK_EQ(optionLen, (socklen_t)sizeof(err));
if (err != 0) {
- LOG(ERROR) << "err = " << err << " (" << strerror(err) << ")";
+ LOGE("err = %d (%s)", err, strerror(err));
reply->setInt32("result", -err);
@@ -343,7 +347,7 @@
request.insert(cseqHeader, i + 2);
- LOG(VERBOSE) << request;
+ LOGV("%s", request.c_str());
size_t numBytesSent = 0;
while (numBytesSent < request.size()) {
@@ -353,7 +357,7 @@
if (n == 0) {
// Server closed the connection.
- LOG(ERROR) << "Server unexpectedly closed the connection.";
+ LOGE("Server unexpectedly closed the connection.");
reply->setInt32("result", ERROR_IO);
reply->post();
@@ -363,7 +367,7 @@
continue;
}
- LOG(ERROR) << "Error sending rtsp request.";
+ LOGE("Error sending rtsp request.");
reply->setInt32("result", -errno);
reply->post();
return;
@@ -438,14 +442,14 @@
ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
if (n == 0) {
// Server closed the connection.
- LOG(ERROR) << "Server unexpectedly closed the connection.";
+ LOGE("Server unexpectedly closed the connection.");
return ERROR_IO;
} else if (n < 0) {
if (errno == EINTR) {
continue;
}
- LOG(ERROR) << "Error reading rtsp response.";
+ LOGE("Error reading rtsp response.");
return -errno;
}
@@ -516,7 +520,7 @@
notify->setObject("buffer", buffer);
notify->post();
} else {
- LOG(WARNING) << "received binary data, but no one cares.";
+ LOGW("received binary data, but no one cares.");
}
return true;
@@ -525,7 +529,7 @@
sp<ARTSPResponse> response = new ARTSPResponse;
response->mStatusLine = statusLine;
- LOG(INFO) << "status: " << response->mStatusLine;
+ LOGI("status: %s", response->mStatusLine.c_str());
ssize_t space1 = response->mStatusLine.find(" ");
if (space1 < 0) {
@@ -555,7 +559,7 @@
break;
}
- LOG(VERBOSE) << "line: " << line;
+ LOGV("line: %s", line.c_str());
ssize_t colonPos = line.find(":");
if (colonPos < 0) {
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 4a8cce85..612caff 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ASessionDescription"
+#include <utils/Log.h>
+
#include "ASessionDescription.h"
#include <media/stagefright/foundation/ADebug.h>
@@ -49,7 +53,7 @@
mFormats.push(AString("[root]"));
AString desc((const char *)data, size);
- LOG(INFO) << desc;
+ LOGI("%s", desc.c_str());
size_t i = 0;
for (;;) {
@@ -102,7 +106,7 @@
key.trim();
value.trim();
- LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+ LOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
mTracks.editItemAt(mTracks.size() - 1).add(key, value);
break;
@@ -110,7 +114,8 @@
case 'm':
{
- LOG(VERBOSE) << "new section '" << AString(line, 2, line.size() - 2) << "'";
+ LOGV("new section '%s'",
+ AString(line, 2, line.size() - 2).c_str());
mTracks.push(Attribs());
mFormats.push(AString(line, 2, line.size() - 2));
@@ -129,7 +134,7 @@
key.trim();
value.trim();
- LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+ LOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
mTracks.editItemAt(mTracks.size() - 1).add(key, value);
break;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index a3864f1..09dc156 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -18,6 +18,10 @@
#define MY_HANDLER_H_
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MyHandler"
+#include <utils/Log.h>
+
#include "APacketSource.h"
#include "ARTPConnection.h"
#include "ARTSPConnection.h"
@@ -137,8 +141,8 @@
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "connection request completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("connection request completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
AString request;
@@ -173,8 +177,8 @@
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "DESCRIBE completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("DESCRIBE completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
sp<RefBase> obj;
@@ -251,8 +255,8 @@
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "SETUP(" << index << ") completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("SETUP(%d) completed with result %d (%s)",
+ index, result, strerror(-result));
if (result == OK) {
CHECK(track != NULL);
@@ -326,8 +330,8 @@
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "PLAY completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("PLAY completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
sp<RefBase> obj;
@@ -404,8 +408,8 @@
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "TEARDOWN completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("TEARDOWN completed with result %d (%s)",
+ result, strerror(-result));
sp<AMessage> reply = new AMessage('disc', id());
@@ -431,7 +435,7 @@
case 'chek':
{
if (mNumAccessUnitsReceived == 0) {
- LOG(INFO) << "stream ended? aborting.";
+ LOGI("stream ended? aborting.");
(new AMessage('abor', id()))->post();
break;
}
@@ -461,7 +465,7 @@
CHECK(msg->findSize("track-index", &trackIndex));
if (trackIndex >= mTracks.size()) {
- LOG(ERROR) << "late packets ignored.";
+ LOGV("late packets ignored.");
break;
}
@@ -469,7 +473,7 @@
int32_t eos;
if (msg->findInt32("eos", &eos)) {
- LOG(INFO) << "received BYE on track index " << trackIndex;
+ LOGI("received BYE on track index %d", trackIndex);
#if 0
track->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
#endif
@@ -484,14 +488,13 @@
uint32_t seqNum = (uint32_t)accessUnit->int32Data();
if (mSeekPending) {
- LOG(INFO) << "we're seeking, dropping stale packet.";
+ LOGV("we're seeking, dropping stale packet.");
break;
}
if (seqNum < track->mFirstSeqNumInSegment) {
- LOG(INFO) << "dropping stale access-unit "
- << "(" << seqNum << " < "
- << track->mFirstSeqNumInSegment << ")";
+ LOGV("dropping stale access-unit (%d < %d)",
+ seqNum, track->mFirstSeqNumInSegment);
break;
}
@@ -506,10 +509,8 @@
if (track->mNewSegment) {
track->mNewSegment = false;
- LOG(VERBOSE) << "first segment unit ntpTime="
- << StringPrintf("0x%016llx", ntpTime)
- << " rtpTime=" << rtpTime
- << " seq=" << seqNum;
+ LOGV("first segment unit ntpTime=0x%016llx rtpTime=%u seq=%d",
+ ntpTime, rtpTime, seqNum);
}
if (mFirstAccessUnit) {
@@ -535,7 +536,7 @@
int32_t damaged;
if (accessUnit->meta()->findInt32("damaged", &damaged)
&& damaged != 0) {
- LOG(INFO) << "ignoring damaged AU";
+ LOGI("ignoring damaged AU");
} else
#endif
{
@@ -608,8 +609,8 @@
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "PLAY completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("PLAY completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
sp<RefBase> obj;
@@ -622,12 +623,12 @@
} else {
parsePlayResponse(response);
- LOG(INFO) << "seek completed.";
+ LOGI("seek completed.");
}
}
if (result != OK) {
- LOG(ERROR) << "seek failed, aborting.";
+ LOGE("seek failed, aborting.");
(new AMessage('abor', id()))->post();
}
@@ -652,11 +653,10 @@
{
if (!mReceivedFirstRTCPPacket) {
if (mTryTCPInterleaving) {
- LOG(WARNING) << "Never received any data, disconnecting.";
+ LOGW("Never received any data, disconnecting.");
(new AMessage('abor', id()))->post();
} else {
- LOG(WARNING)
- << "Never received any data, switching transports.";
+ LOGW("Never received any data, switching transports.");
mTryTCPInterleaving = true;
@@ -700,7 +700,7 @@
}
AString range = response->mHeaders.valueAt(i);
- LOG(VERBOSE) << "Range: " << range;
+ LOGV("Range: %s", range.c_str());
AString val;
CHECK(GetAttribute(range.c_str(), "npt", &val));
@@ -724,7 +724,7 @@
for (List<AString>::iterator it = streamInfos.begin();
it != streamInfos.end(); ++it) {
(*it).trim();
- LOG(VERBOSE) << "streamInfo[" << n << "] = " << *it;
+ LOGV("streamInfo[%d] = %s", n, (*it).c_str());
CHECK(GetAttribute((*it).c_str(), "url", &val));
@@ -748,8 +748,7 @@
uint32_t rtpTime = strtoul(val.c_str(), &end, 10);
- LOG(VERBOSE) << "track #" << n
- << ": rtpTime=" << rtpTime << " <=> npt=" << npt1;
+ LOGV("track #%d: rtpTime=%u <=> ntp=%.2f", n, rtpTime, npt1);
info->mPacketSource->setNormalPlayTimeMapping(
rtpTime, (int64_t)(npt1 * 1E6));
@@ -806,8 +805,7 @@
new APacketSource(mSessionDesc, index);
if (source->initCheck() != OK) {
- LOG(WARNING) << "Unsupported format. Ignoring track #"
- << index << ".";
+ LOGW("Unsupported format. Ignoring track #%d.", index);
sp<AMessage> reply = new AMessage('setu', id());
reply->setSize("index", index);
@@ -830,7 +828,7 @@
info->mFirstSeqNumInSegment = 0;
info->mNewSegment = true;
- LOG(VERBOSE) << "track #" << mTracks.size() << " URL=" << trackURL;
+ LOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str());
AString request = "SETUP ";
request.append(trackURL);
diff --git a/media/libstagefright/rtsp/UDPPusher.cpp b/media/libstagefright/rtsp/UDPPusher.cpp
index 28a343f..576b3ca 100644
--- a/media/libstagefright/rtsp/UDPPusher.cpp
+++ b/media/libstagefright/rtsp/UDPPusher.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "UDPPusher"
+#include <utils/Log.h>
+
#include "UDPPusher.h"
#include <media/stagefright/foundation/ABuffer.h>
@@ -67,7 +71,7 @@
bool UDPPusher::onPush() {
uint32_t length;
if (fread(&length, 1, sizeof(length), mFile) < sizeof(length)) {
- LOG(INFO) << "No more data to push.";
+ LOGI("No more data to push.");
return false;
}
@@ -77,7 +81,7 @@
sp<ABuffer> buffer = new ABuffer(length);
if (fread(buffer->data(), 1, length, mFile) < length) {
- LOG(ERROR) << "File truncated?.";
+ LOGE("File truncated?.");
return false;
}
@@ -89,7 +93,7 @@
uint32_t timeMs;
if (fread(&timeMs, 1, sizeof(timeMs), mFile) < sizeof(timeMs)) {
- LOG(INFO) << "No more data to push.";
+ LOGI("No more data to push.");
return false;
}
@@ -109,7 +113,7 @@
case kWhatPush:
{
if (!onPush() && !(ntohs(mRemoteAddr.sin_port) & 1)) {
- LOG(INFO) << "emulating BYE packet";
+ LOGI("emulating BYE packet");
sp<ABuffer> buffer = new ABuffer(8);
uint8_t *data = buffer->data();
diff --git a/media/libstagefright/rtsp/rtp_test.cpp b/media/libstagefright/rtsp/rtp_test.cpp
index cec6c0c..f0cb5a5 100644
--- a/media/libstagefright/rtsp/rtp_test.cpp
+++ b/media/libstagefright/rtsp/rtp_test.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "rtp_test"
+#include <utils/Log.h>
+
#include <binder/ProcessState.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -200,8 +204,7 @@
continue;
}
- LOG(ERROR) << "decoder returned error "
- << StringPrintf("0x%08x", err);
+ LOGE("decoder returned error 0x%08x", err);
break;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
index db0db70..d5538f1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
@@ -414,13 +414,13 @@
EnergyProbe probe = null;
AudioEffect vc = null;
MediaPlayer mp = null;
+ AudioEffect rvb = null;
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
0);
try {
- probe = new EnergyProbe(0);
// creating a volume controller on output mix ensures that ro.audio.silent mutes
// audio after the effects and not before
vc = new AudioEffect(
@@ -433,11 +433,24 @@
mp = new MediaPlayer();
mp.setDataSource(MediaNames.SINE_200_1000);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
- getReverb(mp.getAudioSessionId());
- mReverb.setRoomLevel((short)0);
- mReverb.setReverbLevel((short)0);
- mReverb.setDecayTime(2000);
- mReverb.setEnabled(true);
+
+ // create reverb with UUID instead of EnvironmentalReverb constructor otherwise an
+ // auxiliary reverb will be chosen by the effect framework as we are on session 0
+ rvb = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("c7a511a0-a3bb-11df-860e-0002a5d5c51b"),
+ 0,
+ 0);
+
+ rvb.setParameter(EnvironmentalReverb.PARAM_ROOM_LEVEL, (short)0);
+ rvb.setParameter(EnvironmentalReverb.PARAM_REVERB_LEVEL, (short)0);
+ rvb.setParameter(EnvironmentalReverb.PARAM_DECAY_TIME, 2000);
+ rvb.setEnabled(true);
+
+ // create probe after reverb so that it is chained behind the reverb in the
+ // effect chain
+ probe = new EnergyProbe(0);
+
mp.prepare();
mp.start();
Thread.sleep(1000);
@@ -460,13 +473,15 @@
loge(msg, "sleep() interrupted");
}
finally {
- releaseReverb();
if (mp != null) {
mp.release();
}
if (vc != null) {
vc.release();
}
+ if (rvb != null) {
+ rvb.release();
+ }
if (probe != null) {
probe.release();
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
index c14319a..fbd8a78 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
@@ -257,13 +257,13 @@
EnergyProbe probe = null;
AudioEffect vc = null;
MediaPlayer mp = null;
+ AudioEffect rvb = null;
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
0);
try {
- probe = new EnergyProbe(0);
// creating a volume controller on output mix ensures that ro.audio.silent mutes
// audio after the effects and not before
vc = new AudioEffect(
@@ -279,6 +279,22 @@
getReverb(mp.getAudioSessionId());
mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
mReverb.setEnabled(true);
+
+ // create reverb with UUID instead of PresetReverb constructor otherwise an auxiliary
+ // reverb will be chosen by the effect framework as we are on session 0
+ rvb = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("172cdf00-a3bc-11df-a72f-0002a5d5c51b"),
+ 0,
+ 0);
+
+ rvb.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_PLATE);
+ rvb.setEnabled(true);
+
+ // create probe after reverb so that it is chained behind the reverb in the
+ // effect chain
+ probe = new EnergyProbe(0);
+
mp.prepare();
mp.start();
Thread.sleep(1000);
@@ -308,6 +324,9 @@
if (vc != null) {
vc.release();
}
+ if (rvb != null) {
+ rvb.release();
+ }
if (probe != null) {
probe.release();
}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 43bb26a..3980189 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -3,16 +3,16 @@
/**
* 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
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * 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.
*/
-->
@@ -24,6 +24,7 @@
<string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi</string>
<string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi</string>
<bool name="def_auto_time">true</bool>
+ <bool name="def_auto_time_zone">true</bool>
<bool name="def_accelerometer_rotation">true</bool>
<!-- Default screen brightness, from 0 to 255. 102 is 40%. -->
<integer name="def_screen_brightness">102</integer>
@@ -31,12 +32,12 @@
<fraction name="def_window_animation_scale">100%</fraction>
<fraction name="def_window_transition_scale">100%</fraction>
<bool name="def_haptic_feedback">true</bool>
-
+
<bool name="def_bluetooth_on">false</bool>
<bool name="def_install_non_market_apps">false</bool>
- <!-- Comma-separated list of location providers.
+ <!-- Comma-separated list of location providers.
Network location is off by default because it requires
- user opt-in via Setup Wizard or Settings.
+ user opt-in via Setup Wizard or Settings.
-->
<string name="def_location_providers_allowed" translatable="false">gps</string>
<bool name="assisted_gps_enabled">true</bool>
@@ -45,11 +46,11 @@
<bool name="def_usb_mass_storage_enabled">true</bool>
<bool name="def_wifi_on">false</bool>
<bool name="def_networks_available_notification_on">true</bool>
-
+
<bool name="def_backup_enabled">false</bool>
<string name="def_backup_transport" translatable="false">android/com.android.internal.backup.LocalTransport</string>
- <!-- Default value for whether or not to pulse the notification LED when there is a
+ <!-- Default value for whether or not to pulse the notification LED when there is a
pending notification -->
<bool name="def_notification_pulse">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 8eb3fe6..9ac832b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -16,6 +16,15 @@
package com.android.providers.settings;
+import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
@@ -36,14 +45,6 @@
import android.text.TextUtils;
import android.util.Log;
-import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
@@ -60,7 +61,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 58;
+ private static final int DATABASE_VERSION = 59;
private Context mContext;
@@ -757,6 +758,23 @@
upgradeVersion = 58;
}
+ if (upgradeVersion == 58) {
+ /* Add default for new Auto Time Zone */
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT INTO secure(name,value)"
+ + " VALUES(?,?);");
+ loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ R.bool.def_auto_time_zone); // Sync timezone to NITZ
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 59;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -1067,7 +1085,10 @@
loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
R.bool.def_auto_time); // Sync time to NITZ
-
+
+ loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ R.bool.def_auto_time_zone); // Sync timezone to NITZ
+
loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
R.integer.def_screen_brightness);
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 024aec5..29ca9a4 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -53,10 +53,6 @@
private final Context mContext;
private final WindowManagerService mWindowManagerService;
- private int mTouchScreenConfig;
- private int mKeyboardConfig;
- private int mNavigationConfig;
-
private static native void nativeInit(Callbacks callbacks);
private static native void nativeStart();
private static native void nativeSetDisplaySize(int displayId, int width, int height);
@@ -79,6 +75,7 @@
private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
private static native void nativeSetFocusedApplication(InputApplication application);
private static native InputDevice nativeGetInputDevice(int deviceId);
+ private static native void nativeGetInputConfiguration(Configuration configuration);
private static native int[] nativeGetInputDeviceIds();
private static native String nativeDump();
@@ -114,10 +111,6 @@
this.mCallbacks = new Callbacks();
- mTouchScreenConfig = Configuration.TOUCHSCREEN_NOTOUCH;
- mKeyboardConfig = Configuration.KEYBOARD_NOKEYS;
- mNavigationConfig = Configuration.NAVIGATION_NONAV;
-
init();
}
@@ -154,9 +147,7 @@
throw new IllegalArgumentException("config must not be null.");
}
- config.touchscreen = mTouchScreenConfig;
- config.keyboard = mKeyboardConfig;
- config.navigation = mNavigationConfig;
+ nativeGetInputConfiguration(config);
}
/**
@@ -367,12 +358,7 @@
}
@SuppressWarnings("unused")
- public void notifyConfigurationChanged(long whenNanos,
- int touchScreenConfig, int keyboardConfig, int navigationConfig) {
- mTouchScreenConfig = touchScreenConfig;
- mKeyboardConfig = keyboardConfig;
- mNavigationConfig = navigationConfig;
-
+ public void notifyConfigurationChanged(long whenNanos) {
mWindowManagerService.sendNewConfiguration();
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1f8d697..c896c94 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7105,6 +7105,12 @@
dumpServicesLocked(fd, pw, args, opti, true);
}
return;
+ } else {
+ // Dumping a single activity?
+ if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
+ return;
+ }
+ pw.println("Bad activity command: " + cmd);
}
}
@@ -7458,6 +7464,82 @@
}
}
+ /**
+ * There are three things that cmd can be:
+ * - a flattened component name that matched an existing activity
+ * - the cmd arg isn't the flattened component name of an existing activity:
+ * dump all activity whose component contains the cmd as a substring
+ * - A hex number of the ActivityRecord object instance.
+ */
+ protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
+ int opti, boolean dumpAll) {
+ String[] newArgs;
+ ComponentName componentName = ComponentName.unflattenFromString(name);
+ int objectId = 0;
+ try {
+ objectId = Integer.parseInt(name, 16);
+ name = null;
+ componentName = null;
+ } catch (RuntimeException e) {
+ }
+ newArgs = new String[args.length - opti];
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
+
+ ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
+ synchronized (this) {
+ for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+ if (componentName != null) {
+ if (r1.intent.getComponent().equals(componentName)) {
+ activities.add(r1);
+ }
+ } else if (name != null) {
+ if (r1.intent.getComponent().flattenToString().contains(name)) {
+ activities.add(r1);
+ }
+ } else if (System.identityHashCode(this) == objectId) {
+ activities.add(r1);
+ }
+ }
+ }
+
+ if (activities.size() <= 0) {
+ return false;
+ }
+
+ for (int i=0; i<activities.size(); i++) {
+ dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
+ }
+ return true;
+ }
+
+ /**
+ * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
+ * there is a thread associated with the activity.
+ */
+ private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
+ boolean dumpAll) {
+ pw.println(" Activity " + r.intent.getComponent().flattenToString());
+ if (dumpAll) {
+ synchronized (this) {
+ pw.print(" * "); pw.println(r);
+ r.dump(pw, " ");
+ }
+ pw.println("");
+ }
+ if (r.app != null && r.app.thread != null) {
+ try {
+ // flush anything that is already in the PrintWriter since the thread is going
+ // to write to the file descriptor directly
+ pw.flush();
+ r.app.thread.dumpActivity(fd, r, args);
+ pw.print("\n");
+ pw.flush();
+ } catch (RemoteException e) {
+ pw.println("got a RemoteException while dumping the activity");
+ }
+ }
+ }
+
boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll) {
boolean needSep = false;
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 3bf6ee4..39ce0b6 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -1171,7 +1171,10 @@
private void reportAGpsStatus(int type, int status) {
switch (status) {
case GPS_REQUEST_AGPS_DATA_CONN:
- int result = mConnMgr.startUsingNetworkFeature(
+ // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
+ // to avoid a race condition with handleUpdateNetworkState()
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+ int result = mConnMgr.startUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
if (result == Phone.APN_ALREADY_ACTIVE) {
if (mAGpsApn != null) {
@@ -1179,11 +1182,13 @@
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
} else {
Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
native_agps_data_conn_failed();
}
} else if (result == Phone.APN_REQUEST_STARTED) {
- mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+ // Nothing to do here
} else {
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
native_agps_data_conn_failed();
}
break;
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index a2ebc69..f1dcd5a 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -172,7 +172,7 @@
SipSessionGroupExt group = mSipGroups.remove(localProfileUri);
if (group != null) {
notifyProfileRemoved(group.getLocalProfile());
- group.closeToNotReceiveCalls();
+ group.close();
if (isWifiOn() && !anyOpened()) releaseWifiLock();
}
}
@@ -449,9 +449,9 @@
}
}
- public void closeToNotReceiveCalls() {
+ public void close() {
mOpened = false;
- mSipGroup.closeToNotReceiveCalls();
+ mSipGroup.close();
mAutoRegistration.stop();
if (DEBUG) Log.d(TAG, " close: " + getUri() + ": "
+ mIncomingCallBroadcastAction);
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index d27c2c6..e3bae56 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -138,6 +138,14 @@
jfieldID mMotionRanges;
} gInputDeviceClassInfo;
+static struct {
+ jclass clazz;
+
+ jfieldID touchscreen;
+ jfieldID keyboard;
+ jfieldID navigation;
+} gConfigurationClassInfo;
+
// ----------------------------------------------------------------------------
static inline nsecs_t now() {
@@ -698,11 +706,7 @@
JNIEnv* env = jniEnv();
- InputConfiguration config;
- mInputManager->getReader()->getInputConfiguration(& config);
-
- env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
- when, config.touchScreen, config.keyboard, config.navigation);
+ env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged, when);
checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
}
@@ -1270,6 +1274,20 @@
return deviceIdsObj;
}
+static void android_server_InputManager_nativeGetInputConfiguration(JNIEnv* env,
+ jclass clazz, jobject configObj) {
+ if (checkInputManagerUnitialized(env)) {
+ return;
+ }
+
+ InputConfiguration config;
+ gNativeInputManager->getInputManager()->getReader()->getInputConfiguration(& config);
+
+ env->SetIntField(configObj, gConfigurationClassInfo.touchscreen, config.touchScreen);
+ env->SetIntField(configObj, gConfigurationClassInfo.keyboard, config.keyboard);
+ env->SetIntField(configObj, gConfigurationClassInfo.navigation, config.navigation);
+}
+
static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
if (checkInputManagerUnitialized(env)) {
return NULL;
@@ -1316,6 +1334,8 @@
(void*) android_server_InputManager_nativeGetInputDevice },
{ "nativeGetInputDeviceIds", "()[I",
(void*) android_server_InputManager_nativeGetInputDeviceIds },
+ { "nativeGetInputConfiguration", "(Landroid/content/res/Configuration;)V",
+ (void*) android_server_InputManager_nativeGetInputConfiguration },
{ "nativeDump", "()Ljava/lang/String;",
(void*) android_server_InputManager_nativeDump },
};
@@ -1343,7 +1363,7 @@
FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
- "notifyConfigurationChanged", "(JIII)V");
+ "notifyConfigurationChanged", "(J)V");
GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
"notifyLidSwitchChanged", "(JZ)V");
@@ -1543,6 +1563,19 @@
GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz,
"mMotionRanges", "[Landroid/view/InputDevice$MotionRange;");
+ // Configuration
+
+ FIND_CLASS(gConfigurationClassInfo.clazz, "android/content/res/Configuration");
+
+ GET_FIELD_ID(gConfigurationClassInfo.touchscreen, gConfigurationClassInfo.clazz,
+ "touchscreen", "I");
+
+ GET_FIELD_ID(gConfigurationClassInfo.keyboard, gConfigurationClassInfo.clazz,
+ "keyboard", "I");
+
+ GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
+ "navigation", "I");
+
return 0;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 5d4dc58..b71cf13 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -16,6 +16,16 @@
package com.android.internal.telephony.cdma;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,19 +48,8 @@
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
-import android.util.Config;
import android.util.TimeUtils;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -987,7 +986,7 @@
mNeedFixZone = false;
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1439,7 +1438,7 @@
}
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1529,6 +1528,14 @@
}
}
+ private boolean getAutoTimeZone() {
+ try {
+ return Settings.System.getInt(cr, Settings.System.AUTO_TIME_ZONE) > 0;
+ } catch (SettingNotFoundException snfe) {
+ return true;
+ }
+ }
+
private void saveNitzTimeZone(String zoneId) {
mSavedTimeZone = zoneId;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index b639eea..83ad552 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,6 +16,17 @@
package com.android.internal.telephony.gsm;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -47,17 +58,6 @@
import android.util.Log;
import android.util.TimeUtils;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -995,7 +995,7 @@
mNeedFixZone = false;
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1476,7 +1476,7 @@
}
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1546,6 +1546,15 @@
}
}
+ private boolean getAutoTimeZone() {
+ try {
+ return Settings.System.getInt(phone.getContext().getContentResolver(),
+ Settings.System.AUTO_TIME_ZONE) > 0;
+ } catch (SettingNotFoundException snfe) {
+ return true;
+ }
+ }
+
private void saveNitzTimeZone(String zoneId) {
mSavedTimeZone = zoneId;
}
diff --git a/tests/DumpRenderTree2/assets/run_apache2.py b/tests/DumpRenderTree2/assets/run_apache2.py
index c799b5c..5edead1 100755
--- a/tests/DumpRenderTree2/assets/run_apache2.py
+++ b/tests/DumpRenderTree2/assets/run_apache2.py
@@ -109,18 +109,17 @@
# Try to execute the commands
logging.info("Will " + run_cmd + " apache2 server.")
- cmd_template = export_envvars_cmd + " && " + apache2_restart_template + directives + conf_file_cmd
# It is worth noting here that if the configuration file with which we restart the server points
- # to a different PidFile it will not work and result in second apache2 instance.
+ # to a different PidFile it will not work and will result in a second apache2 instance.
if (run_cmd == 'restart'):
logging.info("First will stop...")
- execute_cmd(cmd_template % ('stop'))
+ execute_cmd(export_envvars_cmd + " && " + (apache2_restart_template % ('stop')) + directives + conf_file_cmd)
logging.info("Stopped. Will start now...")
# We need to sleep breifly to avoid errors with apache being stopped and started too quickly
time.sleep(0.5)
- execute_cmd(cmd_template % (run_cmd))
+ execute_cmd(export_envvars_cmd + " && " + (apache2_restart_template % (run_cmd)) + directives + conf_file_cmd)
def execute_cmd(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
index 96c1e5e..614b03c 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
@@ -32,7 +32,7 @@
* A class that represent a result of the test. It is responsible for returning the result's
* raw data and generating its own diff in HTML format.
*/
-public abstract class AbstractResult implements Comparable<AbstractResult> {
+public abstract class AbstractResult implements Comparable<AbstractResult>, Serializable {
private static final String LOG_TAG = "AbstractResult";
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index b9fc274..c0ba9e5 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
+import android.net.http.SslError;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -30,19 +31,20 @@
import android.os.Messenger;
import android.os.PowerManager;
import android.os.Process;
-import android.os.RemoteException;
import android.os.PowerManager.WakeLock;
+import android.os.RemoteException;
import android.util.Log;
import android.view.Window;
import android.webkit.ConsoleMessage;
+import android.webkit.GeolocationPermissions;
import android.webkit.HttpAuthHandler;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
-import android.webkit.GeolocationPermissions;
import android.webkit.WebStorage.QuotaUpdater;
import java.io.File;
@@ -74,7 +76,7 @@
}
}
- private static final String LOG_TAG = "LayoutTestExecutor";
+ private static final String LOG_TAG = "LayoutTestsExecutor";
public static final String EXTRA_TESTS_LIST = "TestsList";
public static final String EXTRA_TEST_INDEX = "TestIndex";
@@ -180,6 +182,13 @@
}
handler.cancel();
}
+
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+ // We ignore SSL errors. In particular, the certificate used by the LayoutTests server
+ // produces an error as it lacks a CN field.
+ handler.proceed();
+ }
};
private WebChromeClient mWebChromeClient = new WebChromeClient() {
@@ -236,7 +245,7 @@
* We never display the new window, just create the view and allow it's content to
* execute and be recorded by the executor.
*/
- newWindowWebView = new WebView(LayoutTestsExecutor.this);
+ newWindowWebView = createWebViewWithJavascriptInterfaces();
setupWebView(newWindowWebView);
}
@@ -317,7 +326,7 @@
mCurrentResult = null;
mCurrentAdditionalTextOutput = null;
- mCurrentWebView = new WebView(this);
+ mCurrentWebView = createWebViewWithJavascriptInterfaces();
setupWebView(mCurrentWebView);
mEventSender.reset(mCurrentWebView);
@@ -329,11 +338,26 @@
}
}
+ private static class WebViewWithJavascriptInterfaces extends WebView {
+ public WebViewWithJavascriptInterfaces(
+ Context context, Map<String, Object> javascriptInterfaces) {
+ super(context,
+ null, // attribute set
+ 0, // default style resource ID
+ javascriptInterfaces,
+ false); // is private browsing
+ }
+ }
+ private WebView createWebViewWithJavascriptInterfaces() {
+ Map<String, Object> javascriptInterfaces = new HashMap<String, Object>();
+ javascriptInterfaces.put("layoutTestController", mLayoutTestController);
+ javascriptInterfaces.put("eventSender", mEventSender);
+ return new WebViewWithJavascriptInterfaces(this, javascriptInterfaces);
+ }
+
private void setupWebView(WebView webView) {
webView.setWebViewClient(mWebViewClient);
webView.setWebChromeClient(mWebChromeClient);
- webView.addJavascriptInterface(mLayoutTestController, "layoutTestController");
- webView.addJavascriptInterface(mEventSender, "eventSender");
/**
* Setting a touch interval of -1 effectively disables the optimisation in WebView
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
index e232021..27974e7 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
@@ -42,19 +42,25 @@
private final RadialGradient mRadialGradient;
private final Matrix mMatrix;
private final Matrix mMatrix2;
+ private final Matrix mMatrix3;
GradientsView(Context c) {
super(c);
- mSweepGradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff);
- mRadialGradient = new RadialGradient(100.0f, 100.0f, 100.0f, 0xff000000, 0xffffffff,
+ mSweepGradient = new SweepGradient(0.0f, 0.0f, 0xff000000, 0xffffffff);
+ mRadialGradient = new RadialGradient(0.0f, 0.0f, 100.0f, 0xff000000, 0xffffffff,
Shader.TileMode.MIRROR);
mMatrix = new Matrix();
- mMatrix.setTranslate(50.0f, 50.0f);
+ mMatrix.setRotate(-45, 0.0f, 0.0f);
+ mMatrix.postTranslate(100.0f, 100.0f);
mMatrix2 = new Matrix();
- mMatrix2.setScale(2.0f, 2.0f);
+ mMatrix2.setScale(1.0f, 2.0f);
+ mMatrix2.postRotate(-45, 0.0f, 0.0f);
+
+ mMatrix3 = new Matrix();
+ mMatrix3.setTranslate(100.0f, 100.0f);
mPaint = new Paint();
}
@@ -64,30 +70,42 @@
super.onDraw(canvas);
canvas.drawRGB(255, 255, 255);
- // Bitmap shaders
canvas.save();
canvas.translate(130.0f, 100.0f);
- mSweepGradient.setLocalMatrix(null);
+ mSweepGradient.setLocalMatrix(mMatrix3);
mPaint.setShader(mSweepGradient);
canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
canvas.translate(400.0f, 000.0f);
- mPaint.setShader(mRadialGradient);
- canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
-
- canvas.translate(400.0f, 000.0f);
-
mSweepGradient.setLocalMatrix(mMatrix);
mPaint.setShader(mSweepGradient);
- canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
- canvas.translate(-800.0f, 300.0f);
+ canvas.translate(400.0f, 000.0f);
mSweepGradient.setLocalMatrix(mMatrix2);
mPaint.setShader(mSweepGradient);
canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(-800.0f, 300.0f);
+
+ mRadialGradient.setLocalMatrix(null);
+ mPaint.setShader(mRadialGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(400.0f, 000.0f);
+
+ mRadialGradient.setLocalMatrix(mMatrix);
+ mPaint.setShader(mRadialGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(400.0f, 000.0f);
+
+ mRadialGradient.setLocalMatrix(mMatrix2);
+ mPaint.setShader(mRadialGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
canvas.restore();
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 0910d79..4bc8855 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -116,10 +116,10 @@
}
@Override
- public View createViewFromTag(String name, AttributeSet attrs) {
+ public View createViewFromTag(View parent, String name, AttributeSet attrs) {
View view = null;
try {
- view = super.createViewFromTag(name, attrs);
+ view = super.createViewFromTag(parent, name, attrs);
} catch (InflateException e) {
// try to load the class from using the custom view loader
try {
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 09b392b..c59e20d 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -4,68 +4,196 @@
- Description -
---------------
-makeLayoutLib generates a library used by the Eclipse graphical layout editor
+Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor
to perform layout.
-
- Usage -
---------
- ./makeLayoutLib path/to/android.jar destination.jar
+ ./layoutlib_create path/to/android.jar destination.jar
+
+
+- Design Overview -
+-------------------
+
+Layoutlib_create uses the "android.jar" containing all the Java code used by Android
+as generated by the Android build, right before the classes are converted to a DEX format.
+
+The Android JAR can't be used directly in Eclipse:
+- it contains references to native code (which we want to avoid in Eclipse),
+- some classes need to be overridden, for example all the drawing code that is
+ replaced by Java 2D calls in Eclipse.
+- some of the classes that need to be changed are final and/or we need access
+ to their private internal state.
+
+Consequently this tool:
+- parses the input JAR,
+- modifies some of the classes directly using some bytecode manipulation,
+- filters some packages and removes some that we don't want to end in the output JAR,
+- injects some new classes,
+- and generates a modified JAR file that is suitable for the Android plugin
+ for Eclipse to perform rendering.
+
+The ASM library is used to do the bytecode modification using its visitor pattern API.
+
+The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the
+configuration is done in the main() method and the CreateInfo structure is expected to
+change with the Android platform as new classes are added, changed or removed.
+
+The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the
+platform, that provides all the necessary missing implementation for rendering graphics
+in Eclipse.
- Implementation Notes -
------------------------
-The goal of makeLayoutLib is to list all the classes from the input jar and create a new
-jar that only keeps certain classes and create stubs for all their dependencies.
-
-First the input jar is parsed to find all the classes defined.
-
-In the Main(), the following list of classes are hardcoded (TODO config file later):
-- keep all classes that derive from android.view.View.
-- keep all classes in the android.view and android.widget packages (sub-packages excluded).
-- keep specific classes such as android.policy.PhoneLayoutInflater.
-
-For each class to keep, their dependencies are examined using BCEL.
-A dependency is defined as a class needed to instantiate the given class that should be kept,
-directly or indirectly. So a dependency is a class that is used by the input class, that is
-defined in the input jar and that is not part of the current JRE.
-
-Dependencies are computed recursively.
-
-Once all dependencies are found, the final jar can be created.
-There are three kind of classes to write:
-- classes that are to be kept as-is. They are just dumped in the new jar unchanged.
-- classes that are to be kept yet contain native methods or fields.
-- classes that are just dependencies. We don't want to expose their implementation in the final
- jar.
-
-The implementation of native methods and all methods of mock classes is replaced by a stub
-that throws UnsupportedOperationException.
-
-Incidentally, the access level of native and mock classes needs to be changed in order for
-native methods to be later overridden. Methods that are "final private native" must become
-non-final, non-native and at most protected. Package-default access is changed to public.
-Classes that are final are made non-final. Abstract methods are left untouched.
+The tool works in two phases:
+- first analyze the input jar (AsmAnalyzer class)
+- then generate the output jar (AsmGenerator class),
+- Analyzer
+----------
-----
-20080617 Replace Class
+The goal of the analyzer is to create a graph of all the classes from the input JAR
+with their dependencies and then only keep the ones we want.
-Some classes are basically wrappers over native objects.
-Subclassing doesn't work as most methods are either static or we don't
-control object creation. In this scenario the idea is to be able to
-replace classes in the final jar.
+To do that, the analyzer is created with a list of base classes to keep -- everything
+that derives from these is kept. Currently the one such class is android.view.View:
+since we want to render layouts, anything that is sort of the view needs to be kept.
-Example: android.graphics.Paint would get renamed to OriginalPaint
-in the generated jar. Then in the bridge we'll introduce a replacement
-Paint class that derives from OriginalPaint.
+The analyzer is also given a list of class names to keep in the output.
+This is done using shell-like glob patterns that filter on the fully-qualified
+class names, for example "android.*.R**" ("*" does not matches dots whilst "**" does,
+and "." and "$" are interpreted as-is).
+In practice we almost but not quite request the inclusion of full packages.
+
+With this information, the analyzer parses the input zip to find all the classes.
+All classes deriving from the requested bases classes are kept.
+All classes which name matched the glob pattern are kept.
+The analysis then finds all the dependencies of the classes that are to be kept
+using an ASM visitor on the class, the field types, the method types and annotations types.
+Classes that belong to the current JRE are excluded.
+
+The output of the analyzer is a set of ASM ClassReader instances which are then
+fed to the generator.
+
+
+- Generator
+-----------
+
+The generator is constructed from a CreateInfo struct that acts as a config file
+and lists:
+- the classes to inject in the output JAR -- these classes are directly implemented
+ in layoutlib_create and will be used to interface with the renderer in Eclipse.
+- specific methods to override (see method stubs details below).
+- specific methods to remove based on their return type.
+- specific classes to rename.
+
+Each of these are specific strategies we use to be able to modify the Android code
+to fit within the Eclipse renderer. These strategies are explained beow.
+
+The core method of the generator is transform(): it takes an input ASM ClassReader
+and modifies it to produce a byte array suitable for the final JAR file.
+
+The first step of the transformation is changing the name of the class in case
+we requested the class to be renamed. This uses the RenameClassAdapter to also rename
+all inner classes and references in methods and types. Note that other classes are
+not transformed and keep referencing the original name.
+
+The TransformClassAdapter is then used to process the potentially renamed class.
+All protected or private classes are market as public.
+All classes are made non-final.
+Interfaces are left as-is.
+
+If a method has a return type that must be erased, the whole method is skipped.
+Methods are also changed from protected/private to public.
+The code of the methods is then kept as-is, except for native methods which are
+replaced by a stub. Methods that are to be overridden are also replaced by a stub.
+
+Finally fields are also visited and changed from protected/private to public.
+
+
+- Method stubs
+--------------
+
+As indicated above, all native and overridden methods are replaced by a stub.
+We don't have the code to replace with in layoutlib_create.
+Instead the StubMethodAdapter replaces the code of the method by a call to
+OverrideMethod.invokeX(). When using the final JAR, the bridge can register
+listeners from these overridden method calls based on the method signatures.
+
+The listeners are currently pretty basic: we only pass the signature of the
+method being called, its caller object and a flag indicating whether the
+method was native. We do not currently provide the parameters. The listener
+can however specify the return value of the overridden method.
+
+An extension being worked on is to actually replace these listeners by
+direct calls to a delegate class, complete with parameters.
+
+
+- Strategies
+------------
+
+We currently have 4 strategies to deal with overriding the rendering code
+and make it run in Eclipse. Most of these strategies are implemented hand-in-hand
+by the bridge (which runs in Eclipse) and the generator.
+
+
+1- Class Injection
+
+This is the easiest: we currently inject 4 classes, namely:
+- OverrideMethod and its associated MethodListener and MethodAdapter are used
+ to intercept calls to some specific methods that are stubbed out and change
+ their return value.
+- CreateInfo class, which configured the generator. Not used yet, but could
+ in theory help us track what the generator changed.
+
+
+2- Overriding methods
+
+As explained earlier, the creator doesn't have any replacement code for
+methods to override. Instead it removes the original code and replaces it
+by a call to a specific OveriddeMethod.invokeX(). The bridge then registers
+a listener on the method signature and can provide an implementation.
+
+
+3- Renaming classes
+
+This simply changes the name of a class in its definition, as well as all its
+references in internal inner classes and methods.
+Calls from other classes are not modified -- they keep referencing the original
+class name. This allows the bridge to literally replace an implementation.
+
+An example will make this easier: android.graphics.Paint is the main drawing
+class that we need to replace. To do so, the generator renames Paint to _original_Paint.
+Later the bridge provides its own replacement version of Paint which will be used
+by the rest of the Android stack. The replacement version of Paint can still use
+(either by inheritance or delegation) all the original non-native code of _original_Paint
+if it so desires.
+
+Some of the Android classes are basically wrappers over native objects and since
+we don't have the native code in Eclipse, we need to provide a full alternate
+implementation. Sub-classing doesn't work as some native methods are static and
+we don't control object creation.
This won't rename/replace the inner static methods of a given class.
+4- Method erasure based on return type
+This is mostly an implementation detail of the bridge: in the Paint class
+mentioned above, some inner static classes are used to pass around
+attributes (e.g. FontMetrics, or the Style enum) and all the original implementation
+is native.
+
+In this case we have a strategy that tells the generator that anything returning, for
+example, the inner class Paint$Style in the Paint class should be discarded and the
+bridge will provide its own implementation.
+
+
+--
+end
diff --git a/tools/obbtool/mkobb.sh b/tools/obbtool/mkobb.sh
new file mode 100755
index 0000000..f4cae9a1
--- /dev/null
+++ b/tools/obbtool/mkobb.sh
@@ -0,0 +1,260 @@
+#!/bin/bash
+#
+# 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.
+#
+
+# mkobb.sh - Creates OBB files on Linux machines
+
+# Directory where we should temporarily mount the OBB loopback to copy files
+MOUNTDIR=/tmp
+
+# Presets. Changing these will probably break your OBB on the device
+CRYPTO=blowfish
+FS=vfat
+MKFS=mkfs.vfat
+LOSETUP=losetup
+BLOCK_SIZE=512
+SLOP=512 # Amount of filesystem slop in ${BLOCK_SIZE} blocks
+
+find_binaries() {
+ MKFSBIN=`which ${MKFS}`
+ LOSETUPBIN=`which ${LOSETUP}`
+ MOUNTBIN=`which mount`
+ UMOUNTBIN=`which umount`
+ DDBIN=`which dd`
+ RSYNCBIN=`which rsync`
+}
+
+check_prereqs() {
+ if [ "`uname -s`x" != "Linuxx" ]; then \
+ echo "ERROR: This script only works on Linux!"
+ exit 1
+ fi
+
+ if ! egrep -q "^cryptoloop " /proc/modules; then \
+ echo "ERROR: Could not find cryptoloop in the kernel."
+ echo "Perhaps you need to: modprobe cryptoloop"
+ exit 1
+ fi
+
+ if ! egrep -q "name\s*:\s*${CRYPTO}$" /proc/crypto; then \
+ echo "ERROR: Could not find crypto \`${CRYPTO}' in the kernel."
+ echo "Perhaps you need to: modprobe ${CRYPTO}"
+ exit 1
+ fi
+
+ if ! egrep -q "^\s*${FS}$" /proc/filesystems; then \
+ echo "ERROR: Could not find filesystem \`${FS}' in the kernel."
+ echo "Perhaps you need to: modprobe ${FS}"
+ exit 1
+ fi
+
+ if [ "${MKFSBIN}x" = "x" ]; then \
+ echo "ERROR: Could not find ${MKFS} in your path!"
+ exit 1
+ elif [ ! -x "${MKFSBIN}" ]; then \
+ echo "ERROR: ${MKFSBIN} is not executable!"
+ exit 1
+ fi
+
+ if [ "${LOSETUPBIN}x" = "x" ]; then \
+ echo "ERROR: Could not find ${LOSETUP} in your path!"
+ exit 1
+ elif [ ! -x "${LOSETUPBIN}" ]; then \
+ echo "ERROR: ${LOSETUPBIN} is not executable!"
+ exit 1
+ fi
+}
+
+cleanup() {
+ if [ "${loopdev}x" != "x" ]; then \
+ ${LOSETUPBIN} -d ${loopdev}
+ fi
+}
+
+hidden_prompt() {
+ unset output
+ prompt="$1"
+ outvar="$2"
+ while read -s -n 1 -p "$prompt" c; do \
+ if [ "x$c" = "x" ]; then \
+ break
+ fi
+ prompt='*'
+ output="${output}${c}"
+ done
+ echo
+ eval $outvar="$output"
+ unset output
+}
+
+read_key() {
+ hidden_prompt " Encryption key: " key
+
+ if [ "${key}x" = "x" ]; then \
+ echo "ERROR: An empty key is not allowed!"
+ exit 1
+ fi
+
+ hidden_prompt "Encryption key (again): " key2
+
+ if [ "${key}x" != "${key2}x" ]; then \
+ echo "ERROR: Encryption keys do not match!"
+ exit 1
+ fi
+}
+
+onexit() {
+ if [ "x${temp_mount}" != "x" ]; then \
+ ${UMOUNTBIN} ${temp_mount}
+ rmdir ${temp_mount}
+ fi
+ if [ "x${loop_dev}" != "x" ]; then \
+ ${LOSETUPBIN} -d ${loop_dev}
+ fi
+ if [ "x${tempfile}" != "x" -a -f "${tempfile}" ]; then \
+ rm -f ${tempfile}
+ fi
+ if [ "x${keyfile}" != "x" -a -f "${keyfile}" ]; then \
+ rm -f ${keyfile}
+ fi
+ echo "Fatal error."
+ exit 1
+}
+
+usage() {
+ echo "mkobb.sh -- Create OBB files for use on Android"
+ echo ""
+ echo " -c Use an encrypted OBB; must specify key"
+ echo " -d <directory> Use <directory> as input for OBB files"
+ echo " -k <key> Use <key> to encrypt OBB file"
+ echo " -K Prompt for key to encrypt OBB file"
+ echo " -o <filename> Write OBB file out to <filename>"
+ echo " -v Verbose mode"
+ echo " -h Help; this usage screen"
+}
+
+find_binaries
+check_prereqs
+
+use_crypto=0
+
+args=`getopt -o cd:hk:Ko:v -- "$@"`
+eval set -- "$args"
+
+while true; do \
+ case "$1" in
+ -c) use_crypto=1; shift;;
+ -d) directory=$2; shift 2;;
+ -h) usage; exit 1;;
+ -k) key=$2; shift 2;;
+ -K) prompt_key=1; shift;;
+ -v) verbose=1; shift;;
+ -o) filename=$2; shift 2;;
+ --) shift; break;;
+ *) echo "ERROR: Invalid argument in option parsing! Cannot recover. Ever."; exit 1;;
+ esac
+done
+
+if [ "${directory}x" = "x" -o ! -d "${directory}" ]; then \
+ echo "ERROR: Must specify valid input directory"
+ echo ""
+ usage
+ exit 1;
+fi
+
+if [ "${filename}x" = "x" ]; then \
+ echo "ERROR: Must specify filename"
+ echo ""
+ usage
+ exit 1;
+fi
+
+if [ ${use_crypto} -eq 1 -a "${key}x" = "x" -a 0${prompt_key} -eq 0 ]; then \
+ echo "ERROR: Crypto desired, but no key supplied or requested to prompt for."
+ exit 1
+fi
+
+if [ 0${prompt_key} -eq 1 ]; then \
+ read_key
+fi
+
+outdir=`dirname ${filename}`
+if [ ! -d "${outdir}" ]; then \
+ echo "ERROR: Output directory does not exist: ${outdir}"
+ exit 1
+fi
+
+# Make sure we clean up any stuff we create from here on during error conditions
+trap onexit ERR
+
+tempfile=$(tempfile -d ${outdir}) || ( echo "ERROR: couldn't create temporary file in ${outdir}"; exit 1 )
+
+block_count=`du --apparent-size --block-size=512 ${directory} | awk '{ print $1; }'`
+if [ $? -ne 0 ]; then \
+ echo "ERROR: Couldn't read size of input directory ${directory}"
+ exit 1
+fi
+
+echo "Creating temporary file..."
+${DDBIN} if=/dev/zero of=${tempfile} bs=${BLOCK_SIZE} count=$((${block_count} + ${SLOP})) > /dev/null 2>&1
+if [ $? -ne 0 ]; then \
+ echo "ERROR: creating temporary file: $?"
+fi
+
+loop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next unused device"; exit 1 )
+
+if [ ${use_crypto} -eq 1 ]; then \
+ keyfile=$(tempfile -d ${outdir}) || ( echo "ERROR: could not create temporary key file"; exit 1 )
+ ${LOSETUPBIN} -p 5 -e ${CRYPTO} ${loop_dev} ${tempfile} 5< ${keyfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
+ rm -f ${keyfile}
+else \
+ ${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
+fi
+
+#
+# Create the filesystem
+#
+echo ""
+${MKFSBIN} -I ${loop_dev}
+echo ""
+
+#
+# Make the temporary mount point and mount it
+#
+temp_mount="${MOUNTDIR}/${RANDOM}"
+mkdir ${temp_mount}
+${MOUNTBIN} -t ${FS} -o loop ${loop_dev} ${temp_mount}
+
+#
+# rsync the files!
+#
+echo "Copying files:"
+${RSYNCBIN} -av --no-owner --no-group ${directory}/ ${temp_mount}/
+echo ""
+
+echo "Successfully created \`${filename}'"
+
+#
+# Undo all the temporaries
+#
+umount ${temp_mount}
+rmdir ${temp_mount}
+${LOSETUPBIN} -d ${loop_dev}
+mv ${tempfile} ${filename}
+
+trap - ERR
+
+exit 0