Merge "Hook up CookieManager.removeAllCookie() for the Chromium HTTP stack"
diff --git a/api/current.xml b/api/current.xml
index 6da4a33..22a105a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -108717,32 +108717,6 @@
<parameter name="callbackImmediately" type="boolean">
</parameter>
</method>
-<method name="setRingbackToneEnabled"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="enabled" type="boolean">
-</parameter>
-</method>
-<method name="setRingtoneEnabled"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="enabled" type="boolean">
-</parameter>
-</method>
<method name="setSpeakerMode"
return="void"
abstract="false"
@@ -109441,25 +109415,6 @@
<exception name="SipException" type="android.net.sip.SipException">
</exception>
</method>
-<method name="takeAudioCall"
- return="android.net.sip.SipAudioCall"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="incomingCallIntent" type="android.content.Intent">
-</parameter>
-<parameter name="listener" type="android.net.sip.SipAudioCall.Listener">
-</parameter>
-<parameter name="ringtoneEnabled" type="boolean">
-</parameter>
-<exception name="SipException" type="android.net.sip.SipException">
-</exception>
-</method>
<method name="unregister"
return="void"
abstract="false"
@@ -112680,7 +112635,7 @@
visibility="public"
>
</method>
-<method name="isTagDiscoveryEnabled"
+<method name="isEnabled"
return="boolean"
abstract="false"
native="false"
@@ -152842,6 +152797,17 @@
visibility="public"
>
</field>
+<field name="DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""data""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EMAIL"
type="java.lang.String"
transient="false"
@@ -190804,6 +190770,17 @@
visibility="public"
>
</method>
+<method name="getResult"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getX"
return="float"
abstract="false"
@@ -190846,6 +190823,8 @@
</parameter>
<parameter name="data" type="android.content.ClipData">
</parameter>
+<parameter name="result" type="boolean">
+</parameter>
</method>
<method name="obtain"
return="android.view.DragEvent"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 67bd9f7..35f0249 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -239,19 +239,21 @@
fclose(cmdline);
}
- /* switch to non-root user and group */
- gid_t groups[] = { AID_LOG, AID_SDCARD_RW, AID_MOUNT };
- if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
- LOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
- return -1;
- }
- if (setgid(AID_SHELL) != 0) {
- LOGE("Unable to setgid, aborting: %s\n", strerror(errno));
- return -1;
- }
- if (setuid(AID_SHELL) != 0) {
- LOGE("Unable to setuid, aborting: %s\n", strerror(errno));
- return -1;
+ if (getuid() == 0) {
+ /* switch to non-root user and group */
+ gid_t groups[] = { AID_LOG, AID_SDCARD_RW, AID_MOUNT };
+ if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
+ LOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
+ return -1;
+ }
+ if (setgid(AID_SHELL) != 0) {
+ LOGE("Unable to setgid, aborting: %s\n", strerror(errno));
+ return -1;
+ }
+ if (setuid(AID_SHELL) != 0) {
+ LOGE("Unable to setuid, aborting: %s\n", strerror(errno));
+ return -1;
+ }
}
char path[PATH_MAX], tmp_path[PATH_MAX];
diff --git a/core/java/android/animation/TimeInterpolator.java b/core/java/android/animation/TimeInterpolator.java
index 8d795a8..0f5d8bf 100644
--- a/core/java/android/animation/TimeInterpolator.java
+++ b/core/java/android/animation/TimeInterpolator.java
@@ -23,7 +23,7 @@
public interface TimeInterpolator {
/**
- * Maps a value representing the elapsed fraciton of an animation to a value that represents
+ * Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 79754b8..d60a598 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -523,7 +523,6 @@
for (int i = 0; i < numValues; ++i) {
mValues[i].init();
}
- mCurrentIteration = 0;
mInitialized = true;
}
}
@@ -933,6 +932,7 @@
// This sets the initial value of the animation, prior to actually starting it running
setCurrentPlayTime(getCurrentPlayTime());
}
+ mCurrentIteration = 0;
mPlayingState = STOPPED;
mStartedDelay = false;
sPendingAnimations.add(this);
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index d7a0412..c98128c 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -162,15 +162,10 @@
String path = null;
- if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) == 0) {
- // If the application does not have (Java) code, then no ClassLoader
- // has been set up for it. We will need to do our own search for
- // the native code.
- File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
- System.mapLibraryName(libname));
- if (libraryFile.exists()) {
- path = libraryFile.getPath();
- }
+ File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
+ System.mapLibraryName(libname));
+ if (libraryFile.exists()) {
+ path = libraryFile.getPath();
}
if (path == null) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 643e747..bb0ed6a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -252,9 +252,6 @@
public static final int FLAG_RESTORE_ANY_VERSION = 1<<17;
/**
- * Value for {@link #flags}: Set to true if the application has been
- * installed using the forward lock option.
- *
* Value for {@link #flags}: Set to true if the application is
* currently installed on external/removable/unprotected storage. Such
* applications may not be available if their storage is not currently
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 2c5c909..98bf632 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -177,12 +177,12 @@
* <h4>{@link android.hardware.Sensor#TYPE_ROTATION_VECTOR Sensor.TYPE_ROTATION_VECTOR}:</h4>
* The rotation vector represents the orientation of the device as a combination of an angle
* and an axis, in which the device has rotated through an angle theta around an axis
- * <x, y, z>. The three elements of the rotation vector are
- * <x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>, such that the magnitude of the rotation
+ * <x, y, z>. The three elements of the rotation vector are
+ * <x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>, such that the magnitude of the rotation
* vector is equal to sin(theta/2), and the direction of the rotation vector is equal to the
* direction of the axis of rotation. The three elements of the rotation vector are equal to
* the last three components of a unit quaternion
- * <cos(theta/2), x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>. Elements of the rotation
+ * <cos(theta/2), x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>. Elements of the rotation
* vector are unitless. The x,y, and z axis are defined in the same way as the acceleration
* sensor.
*
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index 2171434..13b97d6 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -28,6 +28,7 @@
String getType(int nativeHandle);
byte[] getUid(int nativeHandle);
boolean isNdef(int nativeHandle);
+ boolean isPresent(int nativeHandle);
byte[] transceive(int nativeHandle, in byte[] data);
int getLastError(int nativeHandle);
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index bc3c6d9..6884abb 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -227,14 +227,17 @@
}
/**
- * Return true if this NFC Adapter is enabled to discover new tags.
+ * Return true if this NFC Adapter has any features enabled.
* <p>
* If this method returns false, then applications should request the user
* turn on NFC tag discovery in Settings.
+ * <p>
+ * If this method returns false, the NFC hardware is guaranteed not to
+ * perform or respond to any NFC communication.
*
* @return true if this NFC Adapter is enabled to discover new tags
*/
- public boolean isTagDiscoveryEnabled() {
+ public boolean isEnabled() {
try {
return mService.isEnabled();
} catch (RemoteException e) {
@@ -244,12 +247,14 @@
}
/**
+ * Enable NFC hardware.
+ * <p>
* NOTE: may block for ~second or more. Poor API. Avoid
* calling from the UI thread.
*
* @hide
*/
- public boolean enableTagDiscovery() {
+ public boolean enable() {
try {
return mService.enable();
} catch (RemoteException e) {
@@ -259,12 +264,16 @@
}
/**
+ * Disable NFC hardware.
+ * No NFC features will work after this call, and the hardware
+ * will not perform or respond to any NFC communication.
+ * <p>
* NOTE: may block for ~second or more. Poor API. Avoid
* calling from the UI thread.
*
* @hide
*/
- public boolean disableTagDiscovery() {
+ public boolean disable() {
try {
return mService.disable();
} catch (RemoteException e) {
diff --git a/core/java/android/nfc/RawTagConnection.java b/core/java/android/nfc/RawTagConnection.java
index 265eb1b..1261db1 100644
--- a/core/java/android/nfc/RawTagConnection.java
+++ b/core/java/android/nfc/RawTagConnection.java
@@ -95,10 +95,16 @@
* returns true.
*/
public boolean isConnected() {
- // TODO(nxp): update mIsConnected when tag goes out of range -
- // but do not do an active prescence check in
- // isConnected()
- return mIsConnected;
+ if (!mIsConnected) {
+ return false;
+ }
+
+ try {
+ return mTagService.isPresent(mTag.mNativeHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service died", e);
+ return false;
+ }
}
/**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index baf3505..0448ec0 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -32,7 +32,6 @@
import android.database.DatabaseUtils;
import android.graphics.Rect;
import android.net.Uri;
-import android.net.Uri.Builder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.DisplayMetrics;
@@ -1444,6 +1443,12 @@
* against the cost of transferring large amounts of denormalized data
* from the Provider.
* </p>
+ * <p>
+ * To reduce the amount of data duplication the contacts provider and directory
+ * providers implementing this protocol are allowed to provide common Contacts
+ * and RawContacts fields in the first row returned for each raw contact only and
+ * leave them as null in subsequent rows.
+ * </p>
*/
public static final class Entity implements BaseColumns, ContactsColumns,
ContactNameColumns, RawContactsColumns, BaseSyncColumns, SyncColumns, DataColumns,
@@ -1838,7 +1843,8 @@
* constituent data rows in a single database transaction
* and causes at most one aggregation pass.
* <pre>
- * ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+ * ArrayList<ContentProviderOperation> ops =
+ * new ArrayList<ContentProviderOperation>();
* ...
* int rawContactInsertIndex = ops.size();
* ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
@@ -2725,7 +2731,9 @@
* <p>
* The same done using ContentProviderOperations:
* <pre>
- * ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+ * ArrayList<ContentProviderOperation> ops =
+ * new ArrayList<ContentProviderOperation>();
+ *
* ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
* .withValue(Data.RAW_CONTACT_ID, rawContactId)
* .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
@@ -2742,7 +2750,9 @@
* Just as with insert, update can be done incrementally or as a batch,
* the batch mode being the preferred method:
* <pre>
- * ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+ * ArrayList<ContentProviderOperation> ops =
+ * new ArrayList<ContentProviderOperation>();
+ *
* ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
* .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
* .withValue(Email.DATA, "somebody@android.com")
@@ -2757,7 +2767,9 @@
* Just as with insert and update, deletion can be done either using the
* {@link ContentResolver#delete} method or using a ContentProviderOperation:
* <pre>
- * ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+ * ArrayList<ContentProviderOperation> ops =
+ * new ArrayList<ContentProviderOperation>();
+ *
* ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI)
* .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
* .build());
@@ -4050,7 +4062,9 @@
* <p>A data kind representing the contact's nickname. For example, for
* Bob Parr ("Mr. Incredible"):
* <pre>
- * ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+ * ArrayList<ContentProviderOperation> ops =
+ * new ArrayList<ContentProviderOperation>();
+ *
* ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
* .withValue(Data.RAW_CONTACT_ID, rawContactId)
* .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
@@ -6645,16 +6659,55 @@
/**
* The extra field that allows the client to supply multiple rows of
- * arbitrary data for the contact (insert or edit). It is a list of
- * ContentValues, one per data row. Supplying this extra is
- * basically equivalent to inserting multiple rows into the
- * {@link Data} table, except the user gets a chance to see and edit
- * them before saving. Each ContentValues object must have a value
- * for {@link Data#MIMETYPE}.
+ * arbitrary data for a single contact created using the {@link Intent#ACTION_INSERT}
+ * or edited using {@link Intent#ACTION_EDIT}. It is an ArrayList of
+ * {@link ContentValues}, one per data row. Supplying this extra is
+ * similar to inserting multiple rows into the {@link Data} table,
+ * except the user gets a chance to see and edit them before saving.
+ * Each ContentValues object must have a value for {@link Data#MIMETYPE}.
+ * If supplied values are not visible in the editor UI, they will be
+ * dropped. Duplicate data will dropped. Some fields
+ * like {@link CommonDataKinds.Email#TYPE Email.TYPE} may be automatically
+ * adjusted to comply with the constraints of the specific account type.
+ * For example, an Exchange contact can only have one phone numbers of type Home,
+ * so the contact editor may choose a different type for this phone number to
+ * avoid dropping the valueable part of the row, which is the phone number.
+ * <p>
+ * Example:
+ * <pre>
+ * ArrayList<ContentValues> data = new ArrayList<ContentValues>();
+ *
+ * ContentValues row1 = new ContentValues();
+ * row1.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
+ * row1.put(Organization.COMPANY, "Android");
+ * data.add(row1);
+ *
+ * ContentValues row2 = new ContentValues();
+ * row2.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ * row2.put(Email.TYPE, Email.TYPE_CUSTOM);
+ * row2.put(Email.LABEL, "Green Bot");
+ * row2.put(Email.ADDRESS, "android@android.com");
+ * data.add(row2);
+ *
+ * Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ * intent.putParcelableArrayListExtra(Insert.DATA, data);
+ *
+ * startActivity(intent);
+ * </pre>
+ */
+ public static final String DATA = "data";
+
+ /**
+ * Used to specify the account in which to create the new contact.
+ * <p>
+ * If this value is not provided, the user is presented with a disambiguation
+ * dialog to chose an account
+ * <p>
+ * Type: {@link Account}
*
* @hide
*/
- public static final String DATA = "data";
+ public static final String ACCOUNT = "com.android.contacts.extra.ACCOUNT";
}
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 17d4aa4..62d2ff2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1642,86 +1642,6 @@
public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
/**
- * Whether nfc is enabled/disabled
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_ON = "nfc_on";
-
- /**
- * Whether nfc secure element is enabled/disabled
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_SECURE_ELEMENT_ON = "nfc_secure_element_on";
-
- /**
- * Whether nfc secure element is enabled/disabled
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_SECURE_ELEMENT_ID = "nfc_secure_element_id";
-
- /**
- * LLCP LTO value
- * @hide
- */
- public static final String NFC_LLCP_LTO = "nfc_llcp_lto";
-
- /**
- * LLCP MIU value
- * @hide
- */
- public static final String NFC_LLCP_MIU = "nfc_llcp_miu";
-
- /**
- * LLCP WKS value
- * @hide
- */
- public static final String NFC_LLCP_WKS = "nfc_llcp_wks";
-
- /**
- * LLCP OPT value
- * @hide
- */
- public static final String NFC_LLCP_OPT = "nfc_llcp_opt";
-
- /**
- * NFC Discovery Reader A
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_DISCOVERY_A = "nfc_discovery_a";
-
- /**
- * NFC Discovery Reader B
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_DISCOVERY_B = "nfc_discovery_b";
-
- /**
- * NFC Discovery Reader Felica
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_DISCOVERY_F = "nfc_discovery_felica";
-
- /**
- * NFC Discovery Reader 15693
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_DISCOVERY_15693 = "nfc_discovery_15693";
-
- /**
- * NFC Discovery NFCIP
- * 0=disabled. 1=enabled.
- * @hide
- */
- public static final String NFC_DISCOVERY_NFCIP = "nfc_discovery_nfcip";
-
- /**
* Show pointer location on screen?
* 0 = no
* 1 = yes
@@ -1895,18 +1815,6 @@
USE_PTP_INTERFACE,
SIP_CALL_OPTIONS,
SIP_RECEIVE_CALLS,
- NFC_ON,
- NFC_SECURE_ELEMENT_ON,
- NFC_SECURE_ELEMENT_ID,
- NFC_LLCP_LTO,
- NFC_LLCP_MIU,
- NFC_LLCP_WKS,
- NFC_LLCP_OPT,
- NFC_DISCOVERY_A,
- NFC_DISCOVERY_B,
- NFC_DISCOVERY_F,
- NFC_DISCOVERY_15693,
- NFC_DISCOVERY_NFCIP,
};
// Settings moved to Settings.Secure
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 2b083dc..9645a17 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -452,17 +452,14 @@
private void dispatchPointer(MotionEvent event) {
synchronized (mLock) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
- if (mPendingMove != null) {
- mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
- mPendingMove.recycle();
- }
mPendingMove = event;
} else {
mPendingMove = null;
}
- Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
- mCaller.sendMessage(msg);
}
+
+ Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
+ mCaller.sendMessage(msg);
}
void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
@@ -905,14 +902,22 @@
mEngine.doOffsetsChanged();
} break;
case MSG_TOUCH_EVENT: {
+ boolean skip = false;
MotionEvent ev = (MotionEvent)message.obj;
- synchronized (mEngine.mLock) {
- if (mEngine.mPendingMove == ev) {
- mEngine.mPendingMove = null;
+ if (ev.getAction() == MotionEvent.ACTION_MOVE) {
+ synchronized (mEngine.mLock) {
+ if (mEngine.mPendingMove == ev) {
+ mEngine.mPendingMove = null;
+ } else {
+ // this is not the motion event we are looking for....
+ skip = true;
+ }
}
}
- if (DEBUG) Log.v(TAG, "Delivering touch event: " + ev);
- mEngine.onTouchEvent(ev);
+ if (!skip) {
+ if (DEBUG) Log.v(TAG, "Delivering touch event: " + ev);
+ mEngine.onTouchEvent(ev);
+ }
ev.recycle();
} break;
default :
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index b1160f0..e7c2231 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -39,12 +39,6 @@
abstract void end();
/**
- * Frees resources taken by this display list. This method must be called
- * before releasing all references.
- */
- abstract void destroy();
-
- /**
* Indicates whether this display list can be replayed or not.
*
* @return True if the display list can be replayed, false otherwise.
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index ebf8505..bbac14c 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -29,6 +29,7 @@
float mX, mY;
ClipDescription mClipDescription;
ClipData mClipData;
+ boolean mDragResult;
private DragEvent mNext;
private RuntimeException mRecycledLocation;
@@ -53,25 +54,27 @@
private DragEvent() {
}
- private void init(int action, float x, float y, ClipDescription description, ClipData data) {
+ private void init(int action, float x, float y, ClipDescription description, ClipData data,
+ boolean result) {
mAction = action;
mX = x;
mY = y;
mClipDescription = description;
mClipData = data;
+ mDragResult = result;
}
static DragEvent obtain() {
- return DragEvent.obtain(0, 0f, 0f, null, null);
+ return DragEvent.obtain(0, 0f, 0f, null, null, false);
}
public static DragEvent obtain(int action, float x, float y,
- ClipDescription description, ClipData data) {
+ ClipDescription description, ClipData data, boolean result) {
final DragEvent ev;
synchronized (gRecyclerLock) {
if (gRecyclerTop == null) {
ev = new DragEvent();
- ev.init(action, x, y, description, data);
+ ev.init(action, x, y, description, data, result);
return ev;
}
ev = gRecyclerTop;
@@ -82,14 +85,14 @@
ev.mRecycled = false;
ev.mNext = null;
- ev.init(action, x, y, description, data);
+ ev.init(action, x, y, description, data, result);
return ev;
}
public static DragEvent obtain(DragEvent source) {
return obtain(source.mAction, source.mX, source.mY,
- source.mClipDescription, source.mClipData);
+ source.mClipDescription, source.mClipData, source.mDragResult);
}
public int getAction() {
@@ -112,6 +115,10 @@
return mClipDescription;
}
+ public boolean getResult() {
+ return mDragResult;
+ }
+
/**
* Recycle the DragEvent, to be re-used by a later caller. After calling
* this function you must never touch the event again.
@@ -146,7 +153,7 @@
public String toString() {
return "DragEvent{" + Integer.toHexString(System.identityHashCode(this))
+ " action=" + mAction + " @ (" + mX + ", " + mY + ") desc=" + mClipDescription
- + " data=" + mClipData
+ + " data=" + mClipData + " result=" + mDragResult
+ "}";
}
@@ -160,6 +167,7 @@
dest.writeInt(mAction);
dest.writeFloat(mX);
dest.writeFloat(mY);
+ dest.writeInt(mDragResult ? 1 : 0);
if (mClipData == null) {
dest.writeInt(0);
} else {
@@ -181,6 +189,7 @@
event.mAction = in.readInt();
event.mX = in.readFloat();
event.mY = in.readFloat();
+ event.mDragResult = (in.readInt() != 0);
if (in.readInt() != 0) {
event.mClipData = ClipData.CREATOR.createFromParcel(in);
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d78c68a..5d9bd1e 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -34,6 +34,11 @@
import android.text.SpannableString;
import android.text.SpannedString;
import android.text.TextUtils;
+import android.util.Finalizers;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
/**
* An implementation of Canvas on top of OpenGL ES 2.0.
@@ -84,22 +89,35 @@
if (mRenderer == 0) {
throw new IllegalStateException("Could not create GLES20Canvas renderer");
+ } else {
+ new CanvasFinalizer(this);
}
}
private native int nCreateRenderer();
private native int nCreateDisplayListRenderer();
- @Override
- public synchronized void destroy() {
- if (mRenderer != 0) {
+ private static native void nDestroyRenderer(int renderer);
+
+ private static class CanvasFinalizer extends Finalizers.ReclaimableReference<GLES20Canvas> {
+ private static final Set<CanvasFinalizer> sFinalizers = Collections.synchronizedSet(
+ new HashSet<CanvasFinalizer>());
+
+ private int mRenderer;
+
+ CanvasFinalizer(GLES20Canvas canvas) {
+ super(canvas, Finalizers.getQueue());
+ mRenderer = canvas.mRenderer;
+ sFinalizers.add(this);
+ }
+
+ @Override
+ public void reclaim() {
nDestroyRenderer(mRenderer);
- mRenderer = 0;
+ sFinalizers.remove(this);
}
}
- private native void nDestroyRenderer(int renderer);
-
///////////////////////////////////////////////////////////////////////////
// Canvas management
///////////////////////////////////////////////////////////////////////////
@@ -178,11 +196,11 @@
private native int nCreateDisplayList(int renderer);
- void destroyDisplayList(int displayList) {
+ static void destroyDisplayList(int displayList) {
nDestroyDisplayList(displayList);
}
- private native void nDestroyDisplayList(int displayList);
+ private static native void nDestroyDisplayList(int displayList);
@Override
public void drawDisplayList(DisplayList displayList) {
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 2886bf3..11e6d30 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -16,6 +16,12 @@
package android.view;
+import android.util.Finalizers;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* An implementation of display list for OpenGL ES 2.0.
*/
@@ -33,8 +39,6 @@
throw new IllegalStateException("Recording has already started");
}
- destroyCanvas();
-
mCanvas = new GLES20Canvas(true, true);
mStarted = true;
mRecorded = false;
@@ -42,16 +46,6 @@
return mCanvas;
}
- private void destroyCanvas() {
- if (mCanvas != null) {
- mCanvas.destroyDisplayList(mNativeDisplayList);
- mCanvas.destroy();
-
- mCanvas = null;
- mNativeDisplayList = 0;
- }
- }
-
@Override
void end() {
if (mCanvas != null) {
@@ -59,16 +53,31 @@
mRecorded = true;
mNativeDisplayList = mCanvas.getDisplayList();
+ new DisplayListFinalizer(this);
}
}
@Override
- void destroy() {
- destroyCanvas();
- }
-
- @Override
boolean isReady() {
return !mStarted && mRecorded;
}
+
+ private static class DisplayListFinalizer extends Finalizers.ReclaimableReference<DisplayList> {
+ private static final Set<DisplayListFinalizer> sFinalizers = Collections.synchronizedSet(
+ new HashSet<DisplayListFinalizer>());
+
+ private int mNativeDisplayList;
+
+ DisplayListFinalizer(GLES20DisplayList displayList) {
+ super(displayList, Finalizers.getQueue());
+ mNativeDisplayList = displayList.mNativeDisplayList;
+ sFinalizers.add(this);
+ }
+
+ @Override
+ public void reclaim() {
+ GLES20Canvas.destroyDisplayList(mNativeDisplayList);
+ sFinalizers.remove(this);
+ }
+ }
}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 22d2fe6..8b8d15e 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -34,14 +34,6 @@
}
/**
- * This method <strong>must</strong> be called before releasing a
- * reference to a hardware canvas. This method is responsible for
- * freeing native resources associated with the hardware. Not
- * invoking this method properly can result in memory leaks.
- */
- public abstract void destroy();
-
- /**
* Invoked before any drawing operation is performed in this canvas.
*/
abstract void onPreDraw();
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 0247f6a..6f4abef 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -414,7 +414,6 @@
@Override
void destroy(boolean full) {
if (full && mCanvas != null) {
- mCanvas.destroy();
mCanvas = null;
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 79ea5b6..23fae42 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -130,6 +130,13 @@
boolean performDrag(IWindow window, IBinder dragToken, float touchX, float touchY,
float thumbCenterX, float thumbCenterY, in ClipData data);
+ /**
+ * Report the result of a drop action targeted to the given window.
+ * consumed is 'true' when the drop was accepted by a valid recipient,
+ * 'false' otherwise.
+ */
+ void reportDropResult(IWindow window, boolean consumed);
+
/**
* Tell the OS that we've just dragged into a View that is willing to accept the drop
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index baa749a..0456463 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7417,7 +7417,6 @@
if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
return null;
}
-
if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
return null;
}
@@ -7425,10 +7424,6 @@
if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED &&
((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDisplayList == null)) {
- if (mDisplayList != null) {
- mDisplayList.destroy();
- }
-
mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
final HardwareCanvas canvas = mDisplayList.start();
@@ -7456,8 +7451,6 @@
canvas.onPostDraw();
mDisplayList.end();
-
- canvas.destroy();
}
}
@@ -7532,7 +7525,6 @@
mUnscaledDrawingCache = null;
}
if (mDisplayList != null) {
- mDisplayList.destroy();
mDisplayList = null;
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f34fd63..7b2703b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1700,10 +1700,10 @@
}
return false;
}
-
+
/**
* {@inheritDoc}
- *
+ *
* @hide
*/
@Override
@@ -1715,10 +1715,10 @@
children[i].dispatchStartTemporaryDetach();
}
}
-
+
/**
* {@inheritDoc}
- *
+ *
* @hide
*/
@Override
@@ -1915,7 +1915,7 @@
if (skipChildren) {
for (int i = 0; i < count; i++) {
getChildAt(i).setVisibility(visibilities[i]);
- }
+ }
}
return b;
@@ -2045,7 +2045,7 @@
*
* @param i The current iteration.
* @return The index of the child to draw this iteration.
- *
+ *
* @see #setChildrenDrawingOrderEnabled(boolean)
* @see #isChildrenDrawingOrderEnabled()
*/
@@ -2186,7 +2186,7 @@
(child.mPrivateFlags & DRAW_ANIMATION) == 0) {
return more;
}
-
+
float alpha = child.getAlpha();
// Bail out early if the view does not need to be drawn
if (alpha <= ViewConfiguration.ALPHA_THRESHOLD && (child.mPrivateFlags & ALPHA_SET) == 0 &&
@@ -2360,7 +2360,7 @@
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = 0; i < count; i++) {
-
+
children[i].setSelected(selected);
}
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ae671b8..ea688ad 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2506,7 +2506,7 @@
final View prevDragView = mCurrentDragView;
// Now dispatch the drag/drop event
- mView.dispatchDragEvent(event);
+ boolean result = mView.dispatchDragEvent(event);
// If we changed apparent drag target, tell the OS about it
if (prevDragView != mCurrentDragView) {
@@ -2521,6 +2521,16 @@
Slog.e(TAG, "Unable to note drag target change");
}
}
+
+ // Report the drop result if necessary
+ if (what == DragEvent.ACTION_DROP) {
+ try {
+ Log.i(TAG, "Reporting drop result: " + result);
+ sWindowSession.reportDropResult(mWindow, result);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to report drop result");
+ }
+ }
}
}
event.recycle();
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index b0a96be..0a91ac4 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -844,8 +844,7 @@
if (mInitialScale > 0) {
scale = mInitialScale;
reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
- } else if (viewState.mViewScale > 0 &&
- (viewState.mMobileSite || !settings.getUseFixedViewport())) {
+ } else if (viewState.mViewScale > 0) {
mTextWrapScale = viewState.mTextWrapScale;
scale = viewState.mViewScale;
reflowText = false;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index f295c41..9e7cc44 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -37,7 +37,6 @@
import android.util.LongSparseArray;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@@ -51,6 +50,7 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@@ -2916,7 +2916,8 @@
delta = Math.max(-(getHeight() - mPaddingBottom - mPaddingTop - 1), delta);
}
- final boolean atEnd = trackMotionScroll(delta, delta);
+ // Don't stop just because delta is zero (it could have been rounded)
+ final boolean atEnd = trackMotionScroll(delta, delta) && (delta != 0);
if (more && !atEnd) {
invalidate();
@@ -3353,7 +3354,10 @@
} else {
mFlingRunnable.endFling();
}
- mFlingRunnable.startScroll(distance, duration);
+ // No sense starting to scroll if we're not going anywhere
+ if (distance != 0) {
+ mFlingRunnable.startScroll(distance, duration);
+ }
}
/**
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 54c4b36..aa68a74 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -154,6 +154,11 @@
int textColorNormal = textColor.getDefaultColor();
mPaint.setColor(textColorNormal);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
+ // to show mOverlayDrawable properly
+ if (mList.getWidth() > 0 && mList.getHeight() > 0) {
+ onSizeChanged(mList.getWidth(), mList.getHeight(), 0, 0);
+ }
mState = STATE_NONE;
}
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index d98f316..7ab95a9 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -152,7 +152,7 @@
* @param context Context used for contained views.
*/
public ListPopupWindow(Context context) {
- this(context, null, 0, 0);
+ this(context, null, com.android.internal.R.attr.listPopupWindowStyle, 0);
}
/**
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 594b1e6..0469e7b 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -26,8 +26,8 @@
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnFocusChangeListener;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
/**
@@ -53,7 +53,8 @@
public class TabWidget extends LinearLayout implements OnFocusChangeListener {
private OnTabSelectionChanged mSelectionChangedListener;
- private int mSelectedTab = 0;
+ // This value will be set to 0 as soon as the first tab is added to TabHost.
+ private int mSelectedTab = -1;
private Drawable mLeftStrip;
private Drawable mRightStrip;
@@ -98,14 +99,18 @@
@Override
protected int getChildDrawingOrder(int childCount, int i) {
- // Always draw the selected tab last, so that drop shadows are drawn
- // in the correct z-order.
- if (i == childCount - 1) {
- return mSelectedTab;
- } else if (i >= mSelectedTab) {
- return i + 1;
- } else {
+ if (mSelectedTab == -1) {
return i;
+ } else {
+ // Always draw the selected tab last, so that drop shadows are drawn
+ // in the correct z-order.
+ if (i == childCount - 1) {
+ return mSelectedTab;
+ } else if (i >= mSelectedTab) {
+ return i + 1;
+ } else {
+ return i;
+ }
}
}
@@ -340,7 +345,9 @@
return;
}
- getChildTabViewAt(mSelectedTab).setSelected(false);
+ if (mSelectedTab != -1) {
+ getChildTabViewAt(mSelectedTab).setSelected(false);
+ }
mSelectedTab = index;
getChildTabViewAt(mSelectedTab).setSelected(true);
mStripMoved = true;
@@ -354,7 +361,9 @@
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
event.setItemCount(getTabCount());
event.setCurrentItemIndex(mSelectedTab);
- getChildTabViewAt(mSelectedTab).dispatchPopulateAccessibilityEvent(event);
+ if (mSelectedTab != -1) {
+ getChildTabViewAt(mSelectedTab).dispatchPopulateAccessibilityEvent(event);
+ }
return true;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d071dd2..be056da 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -990,6 +990,22 @@
setTypeface(tf, styleIndex);
}
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (enabled == isEnabled()) {
+ return;
+ }
+
+ if (!enabled) {
+ // Hide the soft input if the currently active TextView is disabled
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null && imm.isActive(this)) {
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ }
+ }
+ super.setEnabled(enabled);
+ }
+
/**
* Sets the typeface and style in which the text should be displayed,
* and turns on the fake bold and italic bits in the Paint if the
@@ -4640,7 +4656,7 @@
}
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- if (onCheckIsTextEditor()) {
+ if (onCheckIsTextEditor() && isEnabled()) {
if (mInputMethodState == null) {
mInputMethodState = new InputMethodState();
}
@@ -6910,7 +6926,8 @@
return superResult;
}
- if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
+ if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
+ && mText instanceof Spannable && mLayout != null) {
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.onTouchEvent(event);
}
diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
index 98dcb8b..5ab9217 100644
--- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
+++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
@@ -16,6 +16,8 @@
package com.android.internal.app;
+import com.android.internal.os.storage.ExternalStorageFormatter;
+
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -23,10 +25,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
-import android.os.storage.IMountService;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.Environment;
import android.util.Log;
/**
@@ -95,14 +93,9 @@
public void onClick(DialogInterface dialog, int which) {
if (which == POSITIVE_BUTTON) {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService != null) {
- try {
- mountService.formatVolume(Environment.getExternalStorageDirectory().toString());
- } catch (RemoteException e) {
- }
- }
+ Intent intent = new Intent(ExternalStorageFormatter.FORMAT_ONLY);
+ intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
+ startService(intent);
}
// No matter what, finish the activity
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5c1dbaf..224f9a5 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3993,8 +3993,8 @@
// we have gone through a significant charge (from a very low
// level to a now very high level).
if (oldStatus == BatteryManager.BATTERY_STATUS_FULL
- || level >= 100
- || (mDischargeCurrentLevel < 20 && level > 90)) {
+ || level >= 95
+ || (mDischargeCurrentLevel < 30 && level >= 90)) {
doWrite = true;
resetAllStatsLocked();
mDischargeStartLevel = level;
diff --git a/core/java/com/android/internal/util/HierarchicalStateMachine.java b/core/java/com/android/internal/util/HierarchicalStateMachine.java
index aaaa194..7920b72 100644
--- a/core/java/com/android/internal/util/HierarchicalStateMachine.java
+++ b/core/java/com/android/internal/util/HierarchicalStateMachine.java
@@ -1094,7 +1094,9 @@
* @param msg that couldn't be handled.
*/
protected void unhandledMessage(Message msg) {
- Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
+ if (false) {
+ Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
+ }
}
/**
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 880fb6e..f8a80b0 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -255,14 +255,21 @@
static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().textureCache.remove(bitmap);
+ android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
}
-#endif
+#else // !USE_OPENGL_RENDERER
delete bitmap;
+#endif
}
static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
+#ifdef USE_OPENGL_RENDERER
+ if (android::uirenderer::Caches::hasInstance()) {
+ android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
+ }
+#else // !USE_OPENGL_RENDERER
bitmap->setPixels(NULL, NULL);
+#endif // USE_OPENGL_RENDERER
}
// These must match the int values in Bitmap.java
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index cafceab..6667756 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -15,11 +15,6 @@
** limitations under the License.
*/
-// This file was generated from the C++ include file: SkMatrix.h
-// Any changes made to this file will be discarded by the build.
-// To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
-// or one of the auxilary file specifications in device/tools/gluemaker.
-
#include "jni.h"
#include "GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>
@@ -29,13 +24,21 @@
#include "Matrix.h"
+#include <Caches.h>
+
namespace android {
class SkMatrixGlue {
public:
static void finalizer(JNIEnv* env, jobject clazz, SkMatrix* obj) {
+#ifdef USE_OPENGL_RENDERER
+ if (android::uirenderer::Caches::hasInstance()) {
+ android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
+ }
+#else // !USE_OPENGL_RENDERER
delete obj;
+#endif
}
static SkMatrix* create(JNIEnv* env, jobject clazz, const SkMatrix* src) {
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index ca9f371..339c1a4 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -15,11 +15,6 @@
** limitations under the License.
*/
-// This file was generated from the C++ include file: SkPaint.h
-// Any changes made to this file will be discarded by the build.
-// To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
-// or one of the auxilary file specifications in device/tools/gluemaker.
-
#include "jni.h"
#include "GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>
@@ -35,6 +30,7 @@
#include "TextLayout.h"
// temporary for debugging
+#include <Caches.h>
#include <utils/Log.h>
namespace android {
@@ -67,7 +63,13 @@
};
static void finalizer(JNIEnv* env, jobject clazz, SkPaint* obj) {
+#ifdef USE_OPENGL_RENDERER
+ if (android::uirenderer::Caches::hasInstance()) {
+ android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
+ }
+#else // !USE_OPENGL_RENDERER
delete obj;
+#endif
}
static SkPaint* init(JNIEnv* env, jobject clazz) {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index ee44747..79051c2 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -53,13 +53,13 @@
static void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader)
{
+ shader->safeUnref();
+ // skiaShader == NULL when not !USE_OPENGL_RENDERER, so no need to delete it outside the ifdef
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().gradientCache.remove(shader);
+ android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader);
}
#endif
- delete skiaShader;
- shader->safeUnref();
}
static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix)
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 6aa77f6..63d3578 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -35,8 +35,8 @@
#include "android_view_InputChannel.h"
#include "android_view_KeyEvent.h"
-//#define LOG_TRACE(...)
-#define LOG_TRACE(...) LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define LOG_TRACE(...)
+//#define LOG_TRACE(...) LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
namespace android
{
@@ -46,6 +46,7 @@
jmethodID dispatchUnhandledKeyEvent;
jmethodID preDispatchKeyEvent;
+ jmethodID finish;
jmethodID setWindowFlags;
jmethodID setWindowFormat;
jmethodID showIme;
@@ -62,6 +63,7 @@
enum {
CMD_DEF_KEY = 1,
+ CMD_FINISH,
CMD_SET_WINDOW_FORMAT,
CMD_SET_WINDOW_FLAGS,
CMD_SHOW_SOFT_INPUT,
@@ -512,6 +514,11 @@
sp<Looper> looper;
};
+void android_NativeActivity_finish(ANativeActivity* activity) {
+ NativeCode* code = static_cast<NativeCode*>(activity);
+ write_work(code->mainWorkWrite, CMD_FINISH, 0);
+}
+
void android_NativeActivity_setWindowFormat(
ANativeActivity* activity, int32_t format) {
NativeCode* code = static_cast<NativeCode*>(activity);
@@ -538,6 +545,16 @@
// ------------------------------------------------------------------------
+static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+ if (env->ExceptionCheck()) {
+ LOGE("An exception was thrown by callback '%s'.", methodName);
+ LOGE_EX(env);
+ env->ExceptionClear();
+ return true;
+ }
+ return false;
+}
+
/*
* Callback for handling native events on the application's main thread.
*/
@@ -562,6 +579,7 @@
code->env, keyEvent);
code->env->CallVoidMethod(code->clazz,
gNativeActivityClassInfo.dispatchUnhandledKeyEvent, inputEventObj);
+ checkAndClearExceptionFromCallback(code->env, "dispatchUnhandledKeyEvent");
code->nativeInputQueue->finishEvent(keyEvent, true);
}
int seq;
@@ -570,23 +588,32 @@
code->env, keyEvent);
code->env->CallVoidMethod(code->clazz,
gNativeActivityClassInfo.preDispatchKeyEvent, inputEventObj, seq);
+ checkAndClearExceptionFromCallback(code->env, "preDispatchKeyEvent");
}
} break;
+ case CMD_FINISH: {
+ code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
+ checkAndClearExceptionFromCallback(code->env, "finish");
+ } break;
case CMD_SET_WINDOW_FORMAT: {
code->env->CallVoidMethod(code->clazz,
gNativeActivityClassInfo.setWindowFormat, work.arg1);
+ checkAndClearExceptionFromCallback(code->env, "setWindowFormat");
} break;
case CMD_SET_WINDOW_FLAGS: {
code->env->CallVoidMethod(code->clazz,
gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
+ checkAndClearExceptionFromCallback(code->env, "setWindowFlags");
} break;
case CMD_SHOW_SOFT_INPUT: {
code->env->CallVoidMethod(code->clazz,
gNativeActivityClassInfo.showIme, work.arg1);
+ checkAndClearExceptionFromCallback(code->env, "showIme");
} break;
case CMD_HIDE_SOFT_INPUT: {
code->env->CallVoidMethod(code->clazz,
gNativeActivityClassInfo.hideIme, work.arg1);
+ checkAndClearExceptionFromCallback(code->env, "hideIme");
} break;
default:
LOGW("Unknown work command: %d", work.cmd);
@@ -1018,6 +1045,9 @@
gNativeActivityClassInfo.clazz,
"preDispatchKeyEvent", "(Landroid/view/KeyEvent;I)V");
+ GET_METHOD_ID(gNativeActivityClassInfo.finish,
+ gNativeActivityClassInfo.clazz,
+ "finish", "()V");
GET_METHOD_ID(gNativeActivityClassInfo.setWindowFlags,
gNativeActivityClassInfo.clazz,
"setWindowFlags", "(II)V");
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index 7696bb3..53028c3 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "AndroidUnicode"
-#include <jni.h>
+#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
#include "utils/misc.h"
#include "utils/Log.h"
@@ -25,14 +25,6 @@
namespace android {
-static void jniThrowException(JNIEnv* env, const char* exc, const char* msg = NULL)
-{
- jclass excClazz = env->FindClass(exc);
- LOG_ASSERT(excClazz, "Unable to find class %s", exc);
-
- env->ThrowNew(excClazz, msg);
-}
-
static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
jbyteArray infoArray, int n, jboolean haveInfo)
{
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 5d8d419..6b90541 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "AndroidUnicode"
-#include <jni.h>
+#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
#include "utils/misc.h"
#include "utils/Log.h"
@@ -50,14 +50,6 @@
namespace android {
-static void jniThrowException(JNIEnv* env, const char* exc, const char* msg = NULL)
-{
- jclass excClazz = env->FindClass(exc);
- LOG_ASSERT(excClazz, "Unable to find class %s", exc);
-
- env->ThrowNew(excClazz, msg);
-}
-
static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, jbyteArray destArray, int count)
{
jchar* src = env->GetCharArrayElements(srcArray, NULL);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index cfa9a27..6d848a4 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -87,7 +87,7 @@
#endif
}
-static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer) {
RENDERER_LOGD("Destroy OpenGLRenderer");
delete renderer;
@@ -415,7 +415,7 @@
}
static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
- jobject canvas, DisplayList* displayList) {
+ jobject clazz, DisplayList* displayList) {
delete displayList;
}
diff --git a/core/res/res/raw-ar/loaderror.html b/core/res/res/raw-ar/loaderror.html
index edcd63a..aa9805c 100644
--- a/core/res/res/raw-ar/loaderror.html
+++ b/core/res/res/raw-ar/loaderror.html
@@ -2,7 +2,7 @@
<head>
<title>صفحة الويب غير متوفرة</title>
<style type="text/css">
- body { margin-top: 0px; padding-top: 0px; }
+ body { margin-top: 0px; padding-top: 0px; direction: rtl; }
h2 { margin-top: 5px; padding-top: 0px; }
</style>
diff --git a/core/res/res/raw-ar/nodomain.html b/core/res/res/raw-ar/nodomain.html
index bc070f6..2e5849f 100644
--- a/core/res/res/raw-ar/nodomain.html
+++ b/core/res/res/raw-ar/nodomain.html
@@ -2,7 +2,7 @@
<head>
<title>صفحة الويب غير متوفرة</title>
<style type="text/css">
- body { margin-top: 0px; padding-top: 0px; }
+ body { margin-top: 0px; padding-top: 0px; direction: rtl; }
h2 { margin-top: 5px; padding-top: 0px; }
</style>
diff --git a/core/res/res/raw-iw/loaderror.html b/core/res/res/raw-iw/loaderror.html
index 8155432..8d5a53f 100644
--- a/core/res/res/raw-iw/loaderror.html
+++ b/core/res/res/raw-iw/loaderror.html
@@ -2,7 +2,7 @@
<head>
<title>דף אינטרנט לא זמין</title>
<style type="text/css">
- body { margin-top: 0px; padding-top: 0px; }
+ body { margin-top: 0px; padding-top: 0px; direction: rtl; }
h2 { margin-top: 5px; padding-top: 0px; }
</style>
diff --git a/core/res/res/raw-iw/nodomain.html b/core/res/res/raw-iw/nodomain.html
index f7b9f42..0dcd7f8 100644
--- a/core/res/res/raw-iw/nodomain.html
+++ b/core/res/res/raw-iw/nodomain.html
@@ -2,7 +2,7 @@
<head>
<title>דף אינטרנט לא זמין</title>
<style type="text/css">
- body { margin-top: 0px; padding-top: 0px; }
+ body { margin-top: 0px; padding-top: 0px; direction: rtl; }
h2 { margin-top: 5px; padding-top: 0px; }
</style>
diff --git a/core/res/res/values-xlarge/config.xml b/core/res/res/values-xlarge/config.xml
index 813651e..9504d04 100644
--- a/core/res/res/values-xlarge/config.xml
+++ b/core/res/res/values-xlarge/config.xml
@@ -20,9 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Component to be used as the status bar service. Must implement the IStatusBar
- interface. This name is in the ComponentName flattened format (package/class) -->
- <string name="config_statusBarComponent">com.android.systemui/com.android.systemui.statusbar.tablet.TabletStatusBarService</string>
<bool name="config_statusBarCanHide">false</bool>
<!-- see comment in values/config.xml -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index de2b930..a5c9a40 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -20,9 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Component to be used as the status bar service. Must implement the IStatusBar
- interface. This name is in the ComponentName flattened format (package/class) -->
- <string name="config_statusBarComponent">com.android.systemui/com.android.systemui.statusbar.PhoneStatusBarService</string>
<bool name="config_statusBarCanHide">true</bool>
<!-- Do not translate. Defines the slots for the right-hand side icons. That is to say, the
diff --git a/docs/html/sdk/android-2.2.jd b/docs/html/sdk/android-2.2.jd
index 495fd80..063a10f 100644
--- a/docs/html/sdk/android-2.2.jd
+++ b/docs/html/sdk/android-2.2.jd
@@ -42,7 +42,7 @@
<p>Android {@sdkPlatformVersion} is a {@sdkPlatformMajorMinor} platform release including user
features, developer features, API changes, and bug
-fixes. For information on developer features and API changes, see the
+fixes. For information on developer features and API changes, see the
<a href="#api">Framework API</a> section.</p>
<p>For developers, the Android {@sdkPlatformVersion} platform is available as a
@@ -62,7 +62,7 @@
<h2 id="features">Platform Highlights</h2>
-<p>For a list of new user features and platform highlights, see the <a
+<p>For a list of new user features and platform highlights, see the <a
href="http://developer.android.com/sdk/android-2.2-highlights.html">Android
2.2 Platform Highlights</a> document.</p>
@@ -316,8 +316,8 @@
<ul>
<li> New <code>android:backupAgent</code> attribute of the
-<code><application></code> element. Specifies the component name of the
-BackupAgent subclass provided by the application to handle backup/restore
+<code><application></code> element. Specifies the component name of the
+BackupAgent subclass provided by the application to handle backup/restore
operations, if any.</li>
<li> New <code>android:restoreAnyVersion</code> attribute of the
<code><application></code> element. Boolean value that indicates whether
@@ -436,6 +436,11 @@
<p>Localized UI strings match the locales that are accessible
through Settings.</p>
+<p class="note"><strong>Note:</strong> Android supports more locales than are listed above. However,
+the entire collection of locale strings cannot fit on a single system image, so the above list is
+only what's included in the system image for the SDK. All of Android's supported locales are
+available in the <a href="http://source.android.com/">Android Open Source Project</a>.</p>
+
<h2 id="skins">Emulator Skins</h2>
<p>The downloadable platform includes a set of emulator skins that you can use
diff --git a/include/android_runtime/android_app_NativeActivity.h b/include/android_runtime/android_app_NativeActivity.h
index b49e02a..5dbec59 100644
--- a/include/android_runtime/android_app_NativeActivity.h
+++ b/include/android_runtime/android_app_NativeActivity.h
@@ -26,6 +26,9 @@
namespace android {
+extern void android_NativeActivity_finish(
+ ANativeActivity* activity);
+
extern void android_NativeActivity_setWindowFormat(
ANativeActivity* activity, int32_t format);
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index cff38b2..bb469e5 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -152,6 +152,7 @@
bool exceedsFileSizeLimit();
bool use32BitFileOffset() const;
bool exceedsFileDurationLimit();
+ bool isFileStreamable() const;
void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
MPEG4Writer(const MPEG4Writer &);
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 5bf0ccc..f314b09 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -20,6 +20,7 @@
PathCache.cpp \
Program.cpp \
ProgramCache.cpp \
+ ResourceCache.cpp \
SkiaColorFilter.cpp \
SkiaShader.cpp \
TextureCache.cpp \
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index e6e494d..0c704da 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -34,6 +34,7 @@
#include "TextDropShadowCache.h"
#include "FboCache.h"
#include "Line.h"
+#include "ResourceCache.h"
namespace android {
namespace uirenderer {
@@ -138,6 +139,7 @@
TextDropShadowCache dropShadowCache;
FboCache fboCache;
GammaFontRenderer fontRenderer;
+ ResourceCache resourceCache;
Line line;
}; // class Caches
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index b3517c4..a43f164 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -100,39 +100,31 @@
mTFPlayback.reset(&recorder.mTFRecorder);
mTFPlayback.setupBuffer(mReader);
- const SkTDArray<const SkFlatBitmap*>& bitmaps = recorder.getBitmaps();
- mBitmapCount = bitmaps.count();
- if (mBitmapCount > 0) {
- mBitmaps = new SkBitmap[mBitmapCount];
- for (const SkFlatBitmap** flatBitmapPtr = bitmaps.begin();
- flatBitmapPtr != bitmaps.end(); flatBitmapPtr++) {
- const SkFlatBitmap* flatBitmap = *flatBitmapPtr;
- int index = flatBitmap->index() - 1;
- flatBitmap->unflatten(&mBitmaps[index], &mRCPlayback);
- }
- }
+ Caches& caches = Caches::getInstance();
- const SkTDArray<const SkFlatMatrix*>& matrices = recorder.getMatrices();
- mMatrixCount = matrices.count();
- if (mMatrixCount > 0) {
- mMatrices = new SkMatrix[mMatrixCount];
- for (const SkFlatMatrix** matrixPtr = matrices.begin();
- matrixPtr != matrices.end(); matrixPtr++) {
- const SkFlatMatrix* flatMatrix = *matrixPtr;
- flatMatrix->unflatten(&mMatrices[flatMatrix->index() - 1]);
- }
+ const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources();
+ for (size_t i = 0; i < bitmapResources.size(); i++) {
+ SkBitmap* resource = bitmapResources.itemAt(i);
+ mBitmapResources.add(resource);
+ caches.resourceCache.incrementRefcount(resource);
}
-
- const SkTDArray<const SkFlatPaint*>& paints = recorder.getPaints();
- mPaintCount = paints.count();
- if (mPaintCount > 0) {
- mPaints = new SkPaint[mPaintCount];
- for (const SkFlatPaint** flatPaintPtr = paints.begin();
- flatPaintPtr != paints.end(); flatPaintPtr++) {
- const SkFlatPaint* flatPaint = *flatPaintPtr;
- int index = flatPaint->index() - 1;
- flatPaint->unflatten(&mPaints[index], &mRCPlayback, &mTFPlayback);
- }
+ const Vector<SkMatrix*> &matrixResources = recorder.getMatrixResources();
+ for (size_t i = 0; i < matrixResources.size(); i++) {
+ SkMatrix* resource = matrixResources.itemAt(i);
+ mMatrixResources.add(resource);
+ caches.resourceCache.incrementRefcount(resource);
+ }
+ const Vector<SkPaint*> &paintResources = recorder.getPaintResources();
+ for (size_t i = 0; i < paintResources.size(); i++) {
+ SkPaint* resource = paintResources.itemAt(i);
+ mPaintResources.add(resource);
+ caches.resourceCache.incrementRefcount(resource);
+ }
+ const Vector<SkiaShader*> &shaderResources = recorder.getShaderResources();
+ for (size_t i = 0; i < shaderResources.size(); i++) {
+ SkiaShader* resource = shaderResources.itemAt(i);
+ mShaderResources.add(resource);
+ caches.resourceCache.incrementRefcount(resource);
}
mPathHeap = recorder.mPathHeap;
@@ -143,23 +135,32 @@
sk_free((void*) mReader.base());
Caches& caches = Caches::getInstance();
- for (int i = 0; i < mBitmapCount; i++) {
- caches.textureCache.remove(&mBitmaps[i]);
+
+ for (size_t i = 0; i < mBitmapResources.size(); i++) {
+ SkBitmap* resource = mBitmapResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
}
-
- delete[] mBitmaps;
- delete[] mMatrices;
- delete[] mPaints;
-
+ mBitmapResources.clear();
+ for (size_t i = 0; i < mMatrixResources.size(); i++) {
+ SkMatrix* resource = mMatrixResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mMatrixResources.clear();
+ for (size_t i = 0; i < mPaintResources.size(); i++) {
+ SkPaint* resource = mPaintResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mPaintResources.clear();
+ for (size_t i = 0; i < mShaderResources.size(); i++) {
+ SkiaShader* resource = mShaderResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mShaderResources.clear();
mPathHeap->safeUnref();
}
void DisplayList::init() {
- mBitmaps = NULL;
- mMatrices = NULL;
- mPaints = NULL;
mPathHeap = NULL;
- mBitmapCount = mMatrixCount = mPaintCount = 0;
}
void DisplayList::replay(OpenGLRenderer& renderer) {
@@ -280,7 +281,7 @@
}
break;
case SetupShader: {
- // TODO: Implement
+ renderer.setupShader(getShader());
}
break;
case ResetColorFilter: {
@@ -309,7 +310,6 @@
DisplayListRenderer::DisplayListRenderer():
mHeap(HEAP_BLOCK_SIZE), mWriter(MIN_WRITER_SIZE) {
- mBitmapIndex = mMatrixIndex = mPaintIndex = 1;
mPathHeap = NULL;
}
@@ -323,15 +323,33 @@
mPathHeap = NULL;
}
- mBitmaps.reset();
- mMatrices.reset();
- mPaints.reset();
-
mWriter.reset();
mHeap.reset();
mRCRecorder.reset();
mTFRecorder.reset();
+
+ Caches& caches = Caches::getInstance();
+ for (size_t i = 0; i < mBitmapResources.size(); i++) {
+ SkBitmap* resource = mBitmapResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mBitmapResources.clear();
+ for (size_t i = 0; i < mMatrixResources.size(); i++) {
+ SkMatrix* resource = mMatrixResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mMatrixResources.clear();
+ for (size_t i = 0; i < mPaintResources.size(); i++) {
+ SkPaint* resource = mPaintResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mPaintResources.clear();
+ for (size_t i = 0; i < mShaderResources.size(); i++) {
+ SkiaShader* resource = mShaderResources.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mShaderResources.clear();
}
///////////////////////////////////////////////////////////////////////////////
@@ -380,7 +398,7 @@
}
int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* p, int flags) {
+ SkPaint* p, int flags) {
addOp(DisplayList::SaveLayer);
addBounds(left, top, right, bottom);
addPaint(p);
@@ -427,15 +445,15 @@
}
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
- const SkPaint* paint) {
+ SkPaint* paint) {
addOp(DisplayList::DrawBitmap);
addBitmap(bitmap);
addPoint(left, top);
addPaint(paint);
}
-void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix,
- const SkPaint* paint) {
+void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
+ SkPaint* paint) {
addOp(DisplayList::DrawBitmapMatrix);
addBitmap(bitmap);
addMatrix(matrix);
@@ -444,7 +462,7 @@
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) {
+ float dstRight, float dstBottom, SkPaint* paint) {
addOp(DisplayList::DrawBitmapRect);
addBitmap(bitmap);
addBounds(srcLeft, srcTop, srcRight, srcBottom);
@@ -454,7 +472,7 @@
void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, const SkPaint* paint) {
+ float left, float top, float right, float bottom, SkPaint* paint) {
addOp(DisplayList::DrawPatch);
addBitmap(bitmap);
addInts(xDivs, width);
@@ -471,7 +489,7 @@
}
void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
- const SkPaint* paint) {
+ SkPaint* paint) {
addOp(DisplayList::DrawRect);
addBounds(left, top, right, bottom);
addPaint(paint);
@@ -483,7 +501,7 @@
addPaint(paint);
}
-void DisplayListRenderer::drawLines(float* points, int count, const SkPaint* paint) {
+void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
addOp(DisplayList::DrawLines);
addFloats(points, count);
addPaint(paint);
@@ -504,8 +522,8 @@
}
void DisplayListRenderer::setupShader(SkiaShader* shader) {
- // TODO: Implement
- OpenGLRenderer::setupShader(shader);
+ addOp(DisplayList::SetupShader);
+ addShader(shader);
}
void DisplayListRenderer::resetColorFilter() {
@@ -531,58 +549,5 @@
OpenGLRenderer::setupShadow(radius, dx, dy, color);
}
-///////////////////////////////////////////////////////////////////////////////
-// Recording management
-///////////////////////////////////////////////////////////////////////////////
-
-int DisplayListRenderer::find(SkTDArray<const SkFlatPaint*>& paints, const SkPaint* paint) {
- if (paint == NULL) {
- return 0;
- }
-
- SkFlatPaint* flat = SkFlatPaint::Flatten(&mHeap, *paint, mPaintIndex,
- &mRCRecorder, &mTFRecorder);
- int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
- paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0) {
- (void) mHeap.unalloc(flat);
- return paints[index]->index();
- }
-
- index = ~index;
- *paints.insert(index) = flat;
- return mPaintIndex++;
-}
-
-int DisplayListRenderer::find(SkTDArray<const SkFlatMatrix*>& matrices, const SkMatrix* matrix) {
- if (matrix == NULL) {
- return 0;
- }
-
- SkFlatMatrix* flat = SkFlatMatrix::Flatten(&mHeap, *matrix, mMatrixIndex);
- int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
- matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0) {
- (void) mHeap.unalloc(flat);
- return matrices[index]->index();
- }
- index = ~index;
- *matrices.insert(index) = flat;
- return mMatrixIndex++;
-}
-
-int DisplayListRenderer::find(SkTDArray<const SkFlatBitmap*>& bitmaps, const SkBitmap& bitmap) {
- SkFlatBitmap* flat = SkFlatBitmap::Flatten(&mHeap, bitmap, mBitmapIndex, &mRCRecorder);
- int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
- bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0) {
- (void) mHeap.unalloc(flat);
- return bitmaps[index]->index();
- }
- index = ~index;
- *bitmaps.insert(index) = flat;
- return mBitmapIndex++;
-}
-
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 9e6d5b1..c8cd801 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -128,8 +128,11 @@
};
SkBitmap* getBitmap() {
- int index = getInt();
- return &mBitmaps[index - 1];
+ return (SkBitmap*) getInt();
+ }
+
+ SkiaShader* getShader() {
+ return (SkiaShader*) getInt();
}
inline int getIndex() {
@@ -141,11 +144,7 @@
}
SkMatrix* getMatrix() {
- int index = getInt();
- if (index == 0) {
- return NULL;
- }
- return &mMatrices[index - 1];
+ return (SkMatrix*) getInt();
}
SkPath* getPath() {
@@ -153,11 +152,7 @@
}
SkPaint* getPaint() {
- int index = getInt();
- if (index == 0) {
- return NULL;
- }
- return &mPaints[index - 1];
+ return (SkPaint*) getInt();
}
inline float getFloat() {
@@ -186,14 +181,10 @@
PathHeap* mPathHeap;
- SkBitmap* mBitmaps;
- int mBitmapCount;
-
- SkMatrix* mMatrices;
- int mMatrixCount;
-
- SkPaint* mPaints;
- int mPaintCount;
+ Vector<SkBitmap*> mBitmapResources;
+ Vector<SkMatrix*> mMatrixResources;
+ Vector<SkPaint*> mPaintResources;
+ Vector<SkiaShader*> mShaderResources;
mutable SkFlattenableReadBuffer mReader;
@@ -224,7 +215,7 @@
void restoreToCount(int saveCount);
int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* p, int flags);
+ SkPaint* p, int flags);
void translate(float dx, float dy);
void rotate(float degrees);
@@ -235,18 +226,18 @@
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint);
+ void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
+ void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint);
+ float dstRight, float dstBottom, SkPaint* paint);
void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, const SkPaint* paint);
+ float left, float top, float right, float bottom, SkPaint* paint);
void drawColor(int color, SkXfermode::Mode mode);
- void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
+ void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
void drawPath(SkPath* path, SkPaint* paint);
- void drawLines(float* points, int count, const SkPaint* paint);
+ void drawLines(float* points, int count, SkPaint* paint);
void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
void resetShader();
@@ -268,16 +259,20 @@
return mWriter;
}
- const SkTDArray<const SkFlatBitmap*>& getBitmaps() const {
- return mBitmaps;
+ const Vector<SkBitmap*>& getBitmapResources() const {
+ return mBitmapResources;
}
- const SkTDArray<const SkFlatMatrix*>& getMatrices() const {
- return mMatrices;
+ const Vector<SkMatrix*>& getMatrixResources() const {
+ return mMatrixResources;
}
- const SkTDArray<const SkFlatPaint*>& getPaints() const {
- return mPaints;
+ const Vector<SkPaint*>& getPaintResources() const {
+ return mPaintResources;
+ }
+
+ const Vector<SkiaShader*>& getShaderResources() const {
+ return mShaderResources;
}
private:
@@ -338,34 +333,40 @@
addInt(mPathHeap->append(*path));
}
- int find(SkTDArray<const SkFlatPaint*>& paints, const SkPaint* paint);
-
- inline void addPaint(const SkPaint* paint) {
- addInt(find(mPaints, paint));
+ inline void addPaint(SkPaint* paint) {
+ addInt((int)paint);
+ mPaintResources.add(paint);
+ Caches& caches = Caches::getInstance();
+ caches.resourceCache.incrementRefcount(paint);
}
- int find(SkTDArray<const SkFlatMatrix*>& matrices, const SkMatrix* matrix);
-
- inline void addMatrix(const SkMatrix* matrix) {
- addInt(find(mMatrices, matrix));
+ inline void addMatrix(SkMatrix* matrix) {
+ addInt((int)matrix);
+ mMatrixResources.add(matrix);
+ Caches& caches = Caches::getInstance();
+ caches.resourceCache.incrementRefcount(matrix);
}
- int find(SkTDArray<const SkFlatBitmap*>& bitmaps, const SkBitmap& bitmap);
+ inline void addBitmap(SkBitmap* bitmap) {
+ addInt((int)bitmap);
+ mBitmapResources.add(bitmap);
+ Caches& caches = Caches::getInstance();
+ caches.resourceCache.incrementRefcount(bitmap);
+ }
- inline void addBitmap(const SkBitmap* bitmap) {
- addInt(find(mBitmaps, *bitmap));
+ inline void addShader(SkiaShader* shader) {
+ addInt((int)shader);
+ mShaderResources.add(shader);
+ Caches& caches = Caches::getInstance();
+ caches.resourceCache.incrementRefcount(shader);
}
SkChunkAlloc mHeap;
- int mBitmapIndex;
- SkTDArray<const SkFlatBitmap*> mBitmaps;
-
- int mMatrixIndex;
- SkTDArray<const SkFlatMatrix*> mMatrices;
-
- int mPaintIndex;
- SkTDArray<const SkFlatPaint*> mPaints;
+ Vector<SkBitmap*> mBitmapResources;
+ Vector<SkMatrix*> mMatrixResources;
+ Vector<SkPaint*> mPaintResources;
+ Vector<SkiaShader*> mShaderResources;
PathHeap* mPathHeap;
SkWriter32 mWriter;
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
index d492e23..fe75ca2 100644
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ b/libs/hwui/OpenGLDebugRenderer.cpp
@@ -42,21 +42,21 @@
}
int OpenGLDebugRenderer::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* p, int flags) {
+ SkPaint* p, int flags) {
mPrimitivesCount++;
StopWatch w("saveLayer");
return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
}
void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
- const SkPaint* paint) {
+ SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawBitmap");
OpenGLRenderer::drawBitmap(bitmap, left, top, paint);
}
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix,
- const SkPaint* paint) {
+void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
+ SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawBitmapMatrix");
OpenGLRenderer::drawBitmap(bitmap, matrix, paint);
@@ -64,7 +64,7 @@
void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) {
+ float dstRight, float dstBottom, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawBitmapRect");
OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
@@ -73,7 +73,7 @@
void OpenGLDebugRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, const SkPaint* paint) {
+ float left, float top, float right, float bottom, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawPatch");
OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
@@ -87,7 +87,7 @@
}
void OpenGLDebugRenderer::drawRect(float left, float top, float right, float bottom,
- const SkPaint* paint) {
+ SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawRect");
OpenGLRenderer::drawRect(left, top, right, bottom, paint);
@@ -99,7 +99,7 @@
OpenGLRenderer::drawPath(path, paint);
}
-void OpenGLDebugRenderer::drawLines(float* points, int count, const SkPaint* paint) {
+void OpenGLDebugRenderer::drawLines(float* points, int count, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawLines");
OpenGLRenderer::drawLines(points, count, paint);
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
index 4997ef3..ce6a4aa 100644
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ b/libs/hwui/OpenGLDebugRenderer.h
@@ -38,20 +38,20 @@
void finish();
int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* p, int flags);
+ SkPaint* p, int flags);
- void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint);
+ void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
+ void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint);
+ float dstRight, float dstBottom, SkPaint* paint);
void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, const SkPaint* paint);
+ float left, float top, float right, float bottom, SkPaint* paint);
void drawColor(int color, SkXfermode::Mode mode);
- void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
+ void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
void drawPath(SkPath* path, SkPaint* paint);
- void drawLines(float* points, int count, const SkPaint* paint);
+ void drawLines(float* points, int count, SkPaint* paint);
void drawText(const char* text, int bytesCount, int count, float x, float y,
SkPaint* paint);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 633d778..17ef598 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -252,7 +252,7 @@
///////////////////////////////////////////////////////////////////////////////
int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* p, int flags) {
+ SkPaint* p, int flags) {
const GLuint previousFbo = mSnapshot->fbo;
const int count = saveSnapshot(flags);
@@ -623,7 +623,7 @@
// Drawing
///////////////////////////////////////////////////////////////////////////////
-void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
+void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
const float right = left + bitmap->width();
const float bottom = top + bitmap->height();
@@ -639,7 +639,7 @@
drawTextureRect(left, top, right, bottom, texture, paint);
}
-void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) {
+void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height());
const mat4 transform(*matrix);
transform.mapRect(r);
@@ -659,7 +659,7 @@
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkPaint* paint) {
+ SkPaint* paint) {
if (quickReject(dstLeft, dstTop, dstRight, dstBottom)) {
return;
}
@@ -693,7 +693,7 @@
void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, const SkPaint* paint) {
+ float left, float top, float right, float bottom, SkPaint* paint) {
if (quickReject(left, top, right, bottom)) {
return;
}
@@ -719,7 +719,7 @@
}
}
-void OpenGLRenderer::drawLines(float* points, int count, const SkPaint* paint) {
+void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
if (mSnapshot->invisible) return;
int alpha;
@@ -791,7 +791,7 @@
drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
}
-void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) {
+void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) {
if (quickReject(left, top, right, bottom)) {
return;
}
@@ -1206,7 +1206,7 @@
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
- const Texture* texture, const SkPaint* paint) {
+ const Texture* texture, SkPaint* paint) {
int alpha;
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
@@ -1334,7 +1334,7 @@
TextureVertex::setUV(v++, u2, v2);
}
-void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
if (paint) {
if (!mExtensions.hasFramebufferFetch()) {
const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1d8a3d9..b7615fe 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -79,7 +79,7 @@
virtual void restoreToCount(int saveCount);
virtual int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* p, int flags);
+ SkPaint* p, int flags);
virtual int saveLayerAlpha(float left, float top, float right, float bottom,
int alpha, int flags);
@@ -96,18 +96,18 @@
bool quickReject(float left, float top, float right, float bottom);
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- virtual void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
- virtual void drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint);
+ virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
+ virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint);
+ float dstRight, float dstBottom, SkPaint* paint);
virtual void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, const SkPaint* paint);
+ float left, float top, float right, float bottom, SkPaint* paint);
virtual void drawColor(int color, SkXfermode::Mode mode);
- virtual void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
+ virtual void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
virtual void drawPath(SkPath* path, SkPaint* paint);
- virtual void drawLines(float* points, int count, const SkPaint* paint);
+ virtual void drawLines(float* points, int count, SkPaint* paint);
virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
SkPaint* paint);
@@ -231,7 +231,7 @@
* @param paint The paint containing the alpha, blending mode, etc.
*/
void drawTextureRect(float left, float top, float right, float bottom,
- const Texture* texture, const SkPaint* paint);
+ const Texture* texture, SkPaint* paint);
/**
* Draws a textured mesh with the specified texture. If the indices are omitted,
@@ -357,7 +357,7 @@
* @param alpha Where to store the resulting alpha
* @param mode Where to store the resulting xfermode
*/
- inline void getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
+ inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
/**
* Binds the specified texture with the specified wrap modes.
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
new file mode 100644
index 0000000..20b8d6c
--- /dev/null
+++ b/libs/hwui/ResourceCache.cpp
@@ -0,0 +1,219 @@
+/*
+ * 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 <SkPixelRef.h>
+#include "ResourceCache.h"
+#include "Caches.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Resource cache
+///////////////////////////////////////////////////////////////////////////////
+
+void ResourceCache::logCache() {
+ LOGD("ResourceCache: cacheReport:");
+ for (size_t i = 0; i < mCache->size(); ++i) {
+ ResourceReference* ref = mCache->valueAt(i);
+ LOGD(" ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
+ i, mCache->keyAt(i), mCache->valueAt(i));
+ LOGD(" ResourceCache: mCache(%d): refCount, recycled, destroyed, type = %d, %d, %d, %d",
+ i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType);
+ }
+}
+
+ResourceCache::ResourceCache() {
+ mCache = new KeyedVector<void *, ResourceReference *>();
+}
+
+ResourceCache::~ResourceCache() {
+ delete mCache;
+}
+
+void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
+ for (size_t i = 0; i < mCache->size(); ++i) {
+ void* ref = mCache->valueAt(i);
+ }
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL || mCache->size() == 0) {
+ ref = new ResourceReference(resourceType);
+ mCache->add(resource, ref);
+ }
+ ref->refCount++;
+}
+
+void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
+ bitmapResource->pixelRef()->safeRef();
+ bitmapResource->getColorTable()->safeRef();
+ incrementRefcount((void*)bitmapResource, kBitmap);
+}
+
+void ResourceCache::incrementRefcount(SkMatrix* matrixResource) {
+ incrementRefcount((void*)matrixResource, kMatrix);
+}
+
+void ResourceCache::incrementRefcount(SkPaint* paintResource) {
+ incrementRefcount((void*)paintResource, kPaint);
+}
+
+void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
+ shaderResource->getSkShader()->safeRef();
+ incrementRefcount((void*)shaderResource, kShader);
+}
+
+void ResourceCache::decrementRefcount(void* resource) {
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL) {
+ // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
+ return;
+ }
+ ref->refCount--;
+ if (ref->refCount == 0) {
+ deleteResourceReference(resource, ref);
+ }
+}
+
+void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
+ bitmapResource->pixelRef()->safeUnref();
+ bitmapResource->getColorTable()->safeUnref();
+ decrementRefcount((void*)bitmapResource);
+}
+
+void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
+ shaderResource->getSkShader()->safeUnref();
+ decrementRefcount((void*)shaderResource);
+}
+
+void ResourceCache::recycle(SkBitmap* resource) {
+ if (mCache->indexOfKey(resource) < 0) {
+ // not tracking this resource; just recycle the pixel data
+ resource->setPixels(NULL, NULL);
+ return;
+ }
+ recycle((void*) resource);
+}
+
+void ResourceCache::recycle(void* resource) {
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL) {
+ // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
+ return;
+ }
+ ref->recycled = true;
+ if (ref->refCount == 0) {
+ deleteResourceReference(resource, ref);
+ }
+}
+
+void ResourceCache::destructor(SkBitmap* resource) {
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL) {
+ // If we're not tracking this resource, just delete it
+ if (Caches::hasInstance()) {
+ Caches::getInstance().textureCache.remove(resource);
+ }
+ delete resource;
+ return;
+ }
+ ref->destroyed = true;
+ if (ref->refCount == 0) {
+ deleteResourceReference(resource, ref);
+ return;
+ }
+}
+
+void ResourceCache::destructor(SkMatrix* resource) {
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL) {
+ // If we're not tracking this resource, just delete it
+ delete resource;
+ return;
+ }
+ ref->destroyed = true;
+ if (ref->refCount == 0) {
+ deleteResourceReference(resource, ref);
+ return;
+ }
+}
+
+void ResourceCache::destructor(SkPaint* resource) {
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL) {
+ // If we're not tracking this resource, just delete it
+ delete resource;
+ return;
+ }
+ ref->destroyed = true;
+ if (ref->refCount == 0) {
+ deleteResourceReference(resource, ref);
+ return;
+ }
+}
+
+void ResourceCache::destructor(SkiaShader* resource) {
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL) {
+ // If we're not tracking this resource, just delete it
+ if (Caches::hasInstance()) {
+ Caches::getInstance().gradientCache.remove(resource->getSkShader());
+ }
+ delete resource;
+ return;
+ }
+ ref->destroyed = true;
+ if (ref->refCount == 0) {
+ deleteResourceReference(resource, ref);
+ return;
+ }
+}
+
+void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
+ if (ref->recycled && ref->resourceType == kBitmap) {
+ ((SkBitmap*) resource)->setPixels(NULL, NULL);
+ }
+ if (ref->destroyed) {
+ switch (ref->resourceType) {
+ case kBitmap:
+ {
+ SkBitmap* bitmap = (SkBitmap*)resource;
+ if (Caches::hasInstance()) {
+ Caches::getInstance().textureCache.remove(bitmap);
+ }
+ delete bitmap;
+ }
+ break;
+ case kMatrix:
+ delete (SkMatrix*) resource;
+ break;
+ case kPaint:
+ delete (SkPaint*) resource;
+ break;
+ case kShader:
+ SkiaShader* shader = (SkiaShader*)resource;
+ if (Caches::hasInstance()) {
+ Caches::getInstance().gradientCache.remove(shader->getSkShader());
+ }
+ delete shader;
+ break;
+ }
+ }
+ mCache->removeItem(resource);
+ delete ref;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
new file mode 100644
index 0000000..cda2718
--- /dev/null
+++ b/libs/hwui/ResourceCache.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_UI_RESOURCE_CACHE_H
+#define ANDROID_UI_RESOURCE_CACHE_H
+
+#include <SkBitmap.h>
+#include <SkMatrix.h>
+#include <SkPaint.h>
+#include <SkiaShader.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * Type of Resource being cached
+ */
+enum ResourceType {
+ kBitmap,
+ kMatrix,
+ kPaint,
+ kShader,
+};
+
+class ResourceReference {
+public:
+
+ ResourceReference() { refCount = 0; recycled = false; destroyed = false;}
+ ResourceReference(ResourceType type) {
+ refCount = 0; recycled = false; destroyed = false; resourceType = type;
+ }
+
+ int refCount;
+ bool recycled;
+ bool destroyed;
+ ResourceType resourceType;
+};
+
+class ResourceCache {
+ KeyedVector<void *, ResourceReference *>* mCache;
+public:
+ ResourceCache();
+ ~ResourceCache();
+ void incrementRefcount(SkBitmap* resource);
+ void incrementRefcount(SkMatrix* resource);
+ void incrementRefcount(SkPaint* resource);
+ void incrementRefcount(SkiaShader* resource);
+ void incrementRefcount(const void* resource, ResourceType resourceType);
+ void decrementRefcount(void* resource);
+ void decrementRefcount(SkBitmap* resource);
+ void decrementRefcount(SkiaShader* resource);
+ void recycle(void* resource);
+ void recycle(SkBitmap* resource);
+ void destructor(SkBitmap* resource);
+ void destructor(SkMatrix* resource);
+ void destructor(SkPaint* resource);
+ void destructor(SkiaShader* resource);
+private:
+ void deleteResourceReference(void* resource, ResourceReference* ref);
+ void incrementRefcount(void* resource, ResourceType resourceType);
+ void logCache();
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_UI_RESOURCE_CACHE_H
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 2565e65..011991a 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -60,6 +60,10 @@
virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
GLuint* textureUnit);
+ inline SkShader *getSkShader() {
+ return mKey;
+ }
+
inline bool blend() const {
return mBlend;
}
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index e63cc9b..d078d46 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -288,7 +288,7 @@
// Async commands for returning new IDS
-void * rsaTypeCreate(RsContext, RsElement, uint32_t dimCount,
+RsType rsaTypeCreate(RsContext, RsElement, uint32_t dimCount,
const RsDimension *dims, const uint32_t *vals);
diff --git a/libs/rs/rsAdapter.cpp b/libs/rs/rsAdapter.cpp
index ef69b75..1d1425c 100644
--- a/libs/rs/rsAdapter.cpp
+++ b/libs/rs/rsAdapter.cpp
@@ -27,15 +27,11 @@
Adapter1D::Adapter1D(Context *rsc) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
reset();
}
Adapter1D::Adapter1D(Context *rsc, Allocation *a) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
reset();
setAllocation(a);
}
@@ -76,7 +72,7 @@
void Adapter1D::serialize(OStream *stream) const
{
-
+
}
Adapter1D *Adapter1D::createFromStream(Context *rsc, IStream *stream)
@@ -145,15 +141,11 @@
Adapter2D::Adapter2D(Context *rsc) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
reset();
}
Adapter2D::Adapter2D(Context *rsc, Allocation *a) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
reset();
setAllocation(a);
}
@@ -200,7 +192,7 @@
void Adapter2D::serialize(OStream *stream) const
{
-
+
}
Adapter2D *Adapter2D::createFromStream(Context *rsc, IStream *stream)
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 6748bb4..fc41a722 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -57,8 +57,6 @@
void Allocation::init(Context *rsc, const Type *type)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mPtr = NULL;
mCpuWrite = false;
@@ -478,7 +476,7 @@
uint32_t dataSize = stream->loadU32();
if(dataSize != type->getSizeBytes()) {
LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
- delete type;
+ ObjectBase::checkDelete(type);
return NULL;
}
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 9e6fbd5..dc021fc 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -30,8 +30,6 @@
Element::Element(Context *rsc) : ObjectBase(rsc)
{
mBits = 0;
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mFields = NULL;
mFieldCount = 0;
mHasReference = false;
@@ -140,7 +138,7 @@
for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
Element *ee = rsc->mStateElement.mElements[ct];
if(ee->isEqual(elem)) {
- delete elem;
+ ObjectBase::checkDelete(elem);
ee->incUserRef();
return ee;
}
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 633129a..d171a48 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -36,8 +36,6 @@
Font::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mInitialized = false;
mHasKerning = false;
mFace = NULL;
@@ -308,7 +306,7 @@
return newFont;
}
- delete newFont;
+ ObjectBase::checkDelete(newFont);
return NULL;
}
diff --git a/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp
index 8e43f24..761be93 100644
--- a/libs/rs/rsMesh.cpp
+++ b/libs/rs/rsMesh.cpp
@@ -33,8 +33,6 @@
Mesh::Mesh(Context *rsc) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mPrimitives = NULL;
mPrimitivesCount = 0;
mVertexBuffers = NULL;
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 46b1750..724172e 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -22,6 +22,7 @@
#include "rsContextHostStub.h"
#endif
+
using namespace android;
using namespace android::renderscript;
@@ -34,101 +35,119 @@
mRSC = rsc;
mNext = NULL;
mPrev = NULL;
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
+
+#if RS_OBJECT_DEBUG
+ mStack.update(2);
+#endif
rsAssert(rsc);
add();
+ //LOGV("ObjectBase %p con", this);
}
ObjectBase::~ObjectBase()
{
//LOGV("~ObjectBase %p ref %i,%i", this, mUserRefCount, mSysRefCount);
+#if RS_OBJECT_DEBUG
+ mStack.dump();
+#endif
+
+ if(mPrev || mNext) {
+ // While the normal practice is to call remove before we call
+ // delete. Its possible for objects without a re-use list
+ // for avoiding duplication to be created on the stack. In those
+ // cases we need to remove ourself here.
+ asyncLock();
+ remove();
+ asyncUnlock();
+ }
+
rsAssert(!mUserRefCount);
rsAssert(!mSysRefCount);
- remove();
}
void ObjectBase::dumpLOGV(const char *op) const
{
if (mName.size()) {
- LOGV("%s RSobj %p, name %s, refs %i,%i from %s,%i links %p,%p,%p",
- op, this, mName.string(), mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC);
+ LOGV("%s RSobj %p, name %s, refs %i,%i links %p,%p,%p",
+ op, this, mName.string(), mUserRefCount, mSysRefCount, mNext, mPrev, mRSC);
} else {
- LOGV("%s RSobj %p, no-name, refs %i,%i from %s,%i links %p,%p,%p",
- op, this, mUserRefCount, mSysRefCount, mAllocFile, mAllocLine, mNext, mPrev, mRSC);
+ LOGV("%s RSobj %p, no-name, refs %i,%i links %p,%p,%p",
+ op, this, mUserRefCount, mSysRefCount, mNext, mPrev, mRSC);
}
}
void ObjectBase::incUserRef() const
{
- lockUserRef();
- mUserRefCount++;
- unlockUserRef();
- //LOGV("ObjectBase %p inc ref %i", this, mUserRefCount);
-}
-
-void ObjectBase::prelockedIncUserRef() const
-{
- mUserRefCount++;
+ android_atomic_inc(&mUserRefCount);
+ //LOGV("ObjectBase %p incU ref %i, %i", this, mUserRefCount, mSysRefCount);
}
void ObjectBase::incSysRef() const
{
- mSysRefCount ++;
- //LOGV("ObjectBase %p inc ref %i", this, mSysRefCount);
+ android_atomic_inc(&mSysRefCount);
+ //LOGV("ObjectBase %p incS ref %i, %i", this, mUserRefCount, mSysRefCount);
}
-bool ObjectBase::checkDelete() const
+void ObjectBase::preDestroy() const
{
- if (!(mSysRefCount | mUserRefCount)) {
- lockUserRef();
+}
- // Recheck the user ref count since it can be incremented from other threads.
- if (mUserRefCount) {
- unlockUserRef();
- return false;
- }
+bool ObjectBase::checkDelete(const ObjectBase *ref)
+{
+ if (!ref) {
+ return false;
+ }
- if (mRSC && mRSC->props.mLogObjects) {
- dumpLOGV("checkDelete");
- }
- unlockUserRef();
- delete this;
- return true;
+ asyncLock();
+ // This lock protects us against the non-RS threads changing
+ // the ref counts. At this point we should be the only thread
+ // working on them.
+ if (ref->mUserRefCount || ref->mSysRefCount) {
+ asyncUnlock();
+ return false;
+ }
+
+ ref->remove();
+ // At this point we can unlock because there should be no possible way
+ // for another thread to reference this object.
+ ref->preDestroy();
+ asyncUnlock();
+ delete ref;
+ return true;
+}
+
+
+bool ObjectBase::decUserRef() const
+{
+ //LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount);
+ rsAssert(mUserRefCount > 0);
+ if ((android_atomic_dec(&mUserRefCount) <= 1) &&
+ (android_atomic_acquire_load(&mSysRefCount) <= 0)) {
+ return checkDelete(this);
}
return false;
}
-bool ObjectBase::decUserRef() const
-{
- lockUserRef();
- rsAssert(mUserRefCount > 0);
- //dumpLOGV("decUserRef");
- mUserRefCount--;
- unlockUserRef();
- bool ret = checkDelete();
- return ret;
-}
-
bool ObjectBase::zeroUserRef() const
{
- lockUserRef();
- // This can only happen during cleanup and is therefore
- // thread safe.
- mUserRefCount = 0;
- //dumpLOGV("zeroUserRef");
- unlockUserRef();
- bool ret = checkDelete();
- return ret;
+ //LOGV("ObjectBase %p zeroU ref %i, %i", this, mUserRefCount, mSysRefCount);
+ android_atomic_acquire_store(0, &mUserRefCount);
+ if (android_atomic_acquire_load(&mSysRefCount) <= 0) {
+ return checkDelete(this);
+ }
+ return false;
}
bool ObjectBase::decSysRef() const
{
+ //LOGV("ObjectBase %p decS ref %i, %i", this, mUserRefCount, mSysRefCount);
rsAssert(mSysRefCount > 0);
- mSysRefCount --;
- //dumpLOGV("decSysRef");
- return checkDelete();
+ if ((android_atomic_dec(&mSysRefCount) <= 1) &&
+ (android_atomic_acquire_load(&mUserRefCount) <= 0)) {
+ return checkDelete(this);
+ }
+ return false;
}
void ObjectBase::setName(const char *name)
@@ -141,19 +160,19 @@
mName.setTo(name, len);
}
-void ObjectBase::lockUserRef()
+void ObjectBase::asyncLock()
{
pthread_mutex_lock(&gObjectInitMutex);
}
-void ObjectBase::unlockUserRef()
+void ObjectBase::asyncUnlock()
{
pthread_mutex_unlock(&gObjectInitMutex);
}
void ObjectBase::add() const
{
- pthread_mutex_lock(&gObjectInitMutex);
+ asyncLock();
rsAssert(!mNext);
rsAssert(!mPrev);
@@ -164,12 +183,11 @@
}
mRSC->mObjHead = this;
- pthread_mutex_unlock(&gObjectInitMutex);
+ asyncUnlock();
}
void ObjectBase::remove() const
{
- lockUserRef();
//LOGV("calling remove rsc %p", mRSC);
if (!mRSC) {
rsAssert(!mPrev);
@@ -188,7 +206,6 @@
}
mPrev = NULL;
mNext = NULL;
- unlockUserRef();
}
void ObjectBase::zeroAllUserRef(Context *rsc)
@@ -219,7 +236,7 @@
void ObjectBase::dumpAll(Context *rsc)
{
- lockUserRef();
+ asyncLock();
LOGV("Dumping all objects");
const ObjectBase * o = rsc->mObjHead;
@@ -229,22 +246,22 @@
o = o->mNext;
}
- unlockUserRef();
+ asyncUnlock();
}
bool ObjectBase::isValid(const Context *rsc, const ObjectBase *obj)
{
- lockUserRef();
+ asyncLock();
const ObjectBase * o = rsc->mObjHead;
while (o) {
if (o == obj) {
- unlockUserRef();
+ asyncUnlock();
return true;
}
o = o->mNext;
}
- unlockUserRef();
+ asyncUnlock();
return false;
}
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index 8d1ace1..5f03db5 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -19,6 +19,11 @@
#include "rsUtils.h"
+#define RS_OBJECT_DEBUG 0
+
+#if RS_OBJECT_DEBUG
+ #include <utils/CallStack.h>
+#endif
namespace android {
namespace renderscript {
@@ -31,7 +36,6 @@
{
public:
ObjectBase(Context *rsc);
- virtual ~ObjectBase();
void incSysRef() const;
bool decSysRef() const;
@@ -39,7 +43,8 @@
void incUserRef() const;
bool decUserRef() const;
bool zeroUserRef() const;
- void prelockedIncUserRef() const;
+
+ static bool checkDelete(const ObjectBase *);
const char * getName() const {
return mName.string();
@@ -58,13 +63,18 @@
static bool isValid(const Context *rsc, const ObjectBase *obj);
- static void lockUserRef();
- static void unlockUserRef();
+ // The async lock is taken during object creation in non-rs threads
+ // and object deletion in the rs thread.
+ static void asyncLock();
+ static void asyncUnlock();
protected:
- const char *mAllocFile;
- uint32_t mAllocLine;
+ // Called inside the async lock for any object list management that is
+ // necessary in derived classes.
+ virtual void preDestroy() const;
+
Context *mRSC;
+ virtual ~ObjectBase();
private:
static pthread_mutex_t gObjectInitMutex;
@@ -72,14 +82,17 @@
void add() const;
void remove() const;
- bool checkDelete() const;
-
String8 mName;
mutable int32_t mSysRefCount;
mutable int32_t mUserRefCount;
mutable const ObjectBase * mPrev;
mutable const ObjectBase * mNext;
+
+#if RS_OBJECT_DEBUG
+ CallStack mStack;
+#endif
+
};
template<class T>
@@ -104,6 +117,10 @@
}
}
+ ObjectBaseRef & operator= (const ObjectBaseRef &ref) {
+ return ObjectBaseRef(ref);
+ }
+
~ObjectBaseRef() {
clear();
}
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index 10e00e6..72d1b02 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -31,8 +31,6 @@
Program::Program(Context *rsc) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mDirty = true;
mShaderID = 0;
mAttribCount = 0;
@@ -55,8 +53,6 @@
const uint32_t * params, uint32_t paramLength) :
ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mDirty = true;
mShaderID = 0;
mAttribCount = 0;
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 81b4fa4..33399d5 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -36,9 +36,6 @@
uint32_t paramLength) :
Program(rsc, shaderText, shaderLength, params, paramLength)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
-
mConstantColor[0] = 1.f;
mConstantColor[1] = 1.f;
mConstantColor[2] = 1.f;
@@ -182,8 +179,8 @@
ProgramFragmentState::~ProgramFragmentState()
{
- delete mPF;
-
+ ObjectBase::checkDelete(mPF);
+ mPF = NULL;
}
void ProgramFragmentState::init(Context *rsc)
diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp
index 62d060d..5f8c4ba 100644
--- a/libs/rs/rsProgramRaster.cpp
+++ b/libs/rs/rsProgramRaster.cpp
@@ -36,8 +36,6 @@
bool pointSprite) :
Program(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mPointSmooth = pointSmooth;
mLineSmooth = lineSmooth;
mPointSprite = pointSprite;
diff --git a/libs/rs/rsProgramStore.cpp b/libs/rs/rsProgramStore.cpp
index 586a89f..876299f 100644
--- a/libs/rs/rsProgramStore.cpp
+++ b/libs/rs/rsProgramStore.cpp
@@ -33,8 +33,6 @@
ProgramStore::ProgramStore(Context *rsc) :
Program(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mDitherEnable = true;
mBlendEnable = false;
mColorRWriteEnable = true;
@@ -236,8 +234,8 @@
ProgramStoreState::~ProgramStoreState()
{
- delete mPFS;
-
+ ObjectBase::checkDelete(mPFS);
+ mPFS = NULL;
}
void ProgramStoreState::init(Context *rsc)
@@ -258,9 +256,8 @@
void rsi_ProgramStoreBegin(Context * rsc, RsElement in, RsElement out)
{
- delete rsc->mStateFragmentStore.mPFS;
+ ObjectBase::checkDelete(rsc->mStateFragmentStore.mPFS);
rsc->mStateFragmentStore.mPFS = new ProgramStore(rsc);
-
}
void rsi_ProgramStoreDepthFunc(Context *rsc, RsDepthFunc func)
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index a785262..d12439f 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -37,9 +37,6 @@
uint32_t paramLength) :
Program(rsc, shaderText, shaderLength, params, paramLength)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
-
init(rsc);
}
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index 180d78e..cfae7b2 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -33,8 +33,6 @@
Sampler::Sampler(Context *rsc) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
// Should not get called.
rsAssert(0);
}
@@ -47,8 +45,6 @@
RsSamplerValue wrapR,
float aniso) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mMagFilter = magFilter;
mMinFilter = minFilter;
mWrapS = wrapS;
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index c5632b5..ef380d2 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -21,8 +21,6 @@
Script::Script(Context *rsc) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
memset(&mEnviroment, 0, sizeof(mEnviroment));
mSlots = NULL;
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index a2910d7..165fa71 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -35,8 +35,6 @@
ScriptC::ScriptC(Context *rsc) : Script(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mBccScript = NULL;
memset(&mProgram, 0, sizeof(mProgram));
}
@@ -524,11 +522,11 @@
{
ScriptCState *ss = &rsc->mScriptC;
- ObjectBaseRef<ScriptC> s = ss->mScript.get();
+ ObjectBaseRef<ScriptC> s(ss->mScript);
ss->mScript.clear();
+ s->incUserRef();
ss->runCompiler(rsc, s.get());
- s->incUserRef();
ss->clear(rsc);
return s.get();
}
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 27b1b4f..82ad33e 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -27,8 +27,6 @@
Type::Type(Context *rsc) : ObjectBase(rsc)
{
- mAllocFile = __FILE__;
- mAllocLine = __LINE__;
mLODs = 0;
mLODCount = 0;
mAttribs = NULL;
@@ -36,7 +34,7 @@
clear();
}
-Type::~Type()
+void Type::preDestroy()
{
for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
if (mRSC->mStateType.mTypes[ct] == this) {
@@ -44,6 +42,10 @@
break;
}
}
+}
+
+Type::~Type()
+{
if (mLODs) {
delete [] mLODs;
mLODs = NULL;
@@ -401,7 +403,7 @@
}
}
-void * rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimCount,
+RsType rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimCount,
const RsDimension *dims, const uint32_t *vals)
{
Context *rsc = static_cast<Context *>(con);
@@ -428,7 +430,7 @@
}
}
- ObjectBase::lockUserRef();
+ ObjectBase::asyncLock();
for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
Type *t = stc->mTypes[ct];
if (t->getElement() != e) continue;
@@ -437,11 +439,11 @@
if (t->getDimZ() != dimZ) continue;
if (t->getDimLOD() != dimLOD) continue;
if (t->getDimFaces() != dimFaces) continue;
- t->prelockedIncUserRef();
- ObjectBase::unlockUserRef();
+ t->incUserRef();
+ ObjectBase::asyncUnlock();
return t;
}
- ObjectBase::unlockUserRef();
+ ObjectBase::asyncUnlock();
Type * st = new Type(rsc);
st->incUserRef();
@@ -453,9 +455,9 @@
st->setDimFaces(dimFaces);
st->compute();
- ObjectBase::lockUserRef();
+ ObjectBase::asyncLock();
stc->mTypes.push(st);
- ObjectBase::unlockUserRef();
+ ObjectBase::asyncUnlock();
return st;
}
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index a0c77ab..6b89413 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -124,6 +124,9 @@
bool isValidGLComponent(uint32_t fieldIdx);
void makeGLComponents();
+protected:
+ virtual void preDestroy();
+
private:
Type(const Type &);
};
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 97a7528..bc08e0a 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -839,7 +839,7 @@
}
// See if this device has a gamepad.
- for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES); i++) {
+ for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
break;
diff --git a/libs/utils/StreamingZipInflater.cpp b/libs/utils/StreamingZipInflater.cpp
index 7ebde78..1f62ac5 100644
--- a/libs/utils/StreamingZipInflater.cpp
+++ b/libs/utils/StreamingZipInflater.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define LOG_NDEBUG 1
#define LOG_TAG "szipinf"
#include <utils/Log.h>
@@ -157,7 +158,7 @@
*/
int result = Z_OK;
if (mStreamNeedsInit) {
- LOGI("Initializing zlib to inflate");
+ LOGD("Initializing zlib to inflate");
result = inflateInit2(&mInflateState, -MAX_WBITS);
mStreamNeedsInit = false;
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6c8287c..9e79aa9 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -41,7 +41,10 @@
static const int64_t kMax32BitFileSize = 0x007fffffffLL;
static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
static const uint8_t kNalUnitTypePicParamSet = 0x08;
-static const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 10000000LL; // 10s
+
+// Using longer adjustment period to suppress fluctuations in
+// the audio encoding paths
+static const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 600000000LL; // 10 minutes
class MPEG4Writer::Track {
public:
@@ -309,11 +312,10 @@
//
// Statistical analysis shows that metadata usually accounts
// for a small portion of the total file size, usually < 0.6%.
- // Currently, lets set to 0.4% for now.
- // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
+ // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
// where 1MB is the common file size limit for MMS application.
- // The default MAX _MOOV_BOX_SIZE value is based on about 4
+ // The default MAX _MOOV_BOX_SIZE value is based on about 3
// minute video recording with a bit rate about 3 Mbps, because
// statistics also show that most of the video captured are going
// to be less than 3 minutes.
@@ -321,20 +323,33 @@
// If the estimation is wrong, we will pay the price of wasting
// some reserved space. This should not happen so often statistically.
static const int32_t factor = mUse32BitOffset? 1: 2;
- static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB
+ static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB
static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
int64_t size = MIN_MOOV_BOX_SIZE;
+ // Max file size limit is set
if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
- size = mMaxFileSizeLimitBytes * 4 / 1000;
- } else if (mMaxFileDurationLimitUs != 0) {
- if (bitRate <= 0) {
- // We could not estimate the file size since bitRate is not set.
- size = MIN_MOOV_BOX_SIZE;
- } else {
- size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
+ size = mMaxFileSizeLimitBytes * 6 / 1000;
+ }
+
+ // Max file duration limit is set
+ if (mMaxFileDurationLimitUs != 0) {
+ if (bitRate > 0) {
+ int64_t size2 =
+ ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
+ if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
+ // When both file size and duration limits are set,
+ // we use the smaller limit of the two.
+ if (size > size2) {
+ size = size2;
+ }
+ } else {
+ // Only max file duration limit is set
+ size = size2;
+ }
}
}
+
if (size < MIN_MOOV_BOX_SIZE) {
size = MIN_MOOV_BOX_SIZE;
}
@@ -787,6 +802,10 @@
write(data, 1, size, mFile);
}
+bool MPEG4Writer::isFileStreamable() const {
+ return mStreamableFile;
+}
+
bool MPEG4Writer::exceedsFileSizeLimit() {
// No limit
if (mMaxFileSizeLimitBytes == 0) {
@@ -799,7 +818,7 @@
nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
}
- return (nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes);
+ return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
}
bool MPEG4Writer::exceedsFileDurationLimit() {
@@ -887,12 +906,16 @@
int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
- mEstimatedTrackSizeBytes = mMdatSizeBytes + // media data size
- mNumStscTableEntries * 12 + // stsc box size
- mNumStssTableEntries * 4 + // stss box size
- mNumSttsTableEntries * 8 + // stts box size
- stcoBoxSizeBytes + // stco box size
- stszBoxSizeBytes; // stsz box size
+ mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size
+ if (!mOwner->isFileStreamable()) {
+ // Reserved free space is not large enough to hold
+ // all meta data and thus wasted.
+ mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size
+ mNumStssTableEntries * 4 + // stss box size
+ mNumSttsTableEntries * 8 + // stts box size
+ stcoBoxSizeBytes + // stco box size
+ stszBoxSizeBytes; // stsz box size
+ }
}
void MPEG4Writer::Track::addOneStscTableEntry(
@@ -1155,7 +1178,7 @@
startTimeUs = 0;
}
- mIsRealTimeRecording = false;
+ mIsRealTimeRecording = true;
{
int32_t isNotRealTime;
if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
diff --git a/native/android/native_activity.cpp b/native/android/native_activity.cpp
index 0c6823a..056255f 100644
--- a/native/android/native_activity.cpp
+++ b/native/android/native_activity.cpp
@@ -21,6 +21,10 @@
using namespace android;
+void ANativeActivity_finish(ANativeActivity* activity) {
+ android_NativeActivity_finish(activity);
+}
+
void ANativeActivity_setWindowFormat(ANativeActivity* activity, int32_t format) {
android_NativeActivity_setWindowFormat(activity, format);
}
diff --git a/native/include/android/native_activity.h b/native/include/android/native_activity.h
index d74e1ce..a8f11c9 100644
--- a/native/include/android/native_activity.h
+++ b/native/include/android/native_activity.h
@@ -227,6 +227,12 @@
*/
extern ANativeActivity_createFunc ANativeActivity_onCreate;
+/**
+ * Finish the given activity. Its finish() method will be called, causing it
+ * to be stopped and destroyed.
+ */
+void ANativeActivity_finish(ANativeActivity* activity);
+
void ANativeActivity_setWindowFormat(ANativeActivity* activity, int32_t format);
void ANativeActivity_setWindowFlags(ANativeActivity* activity,
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 239dc05..e38b9cc 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -840,7 +840,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
static char const * const gVendorString = "Google Inc.";
-static char const * const gVersionString = "1.2 Android Driver 1.1.0";
+static char const * const gVersionString = "1.2 Android Driver 1.2.0";
static char const * const gClientApiString = "OpenGL ES";
static char const * const gExtensionsString =
"EGL_KHR_image_base "
@@ -947,6 +947,7 @@
{ EGL_RED_SIZE, 5 },
{ EGL_DEPTH_SIZE, 0 },
{ EGL_CONFIG_ID, 0 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
@@ -958,6 +959,7 @@
{ EGL_RED_SIZE, 5 },
{ EGL_DEPTH_SIZE, 16 },
{ EGL_CONFIG_ID, 1 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
@@ -970,6 +972,7 @@
{ EGL_RED_SIZE, 8 },
{ EGL_DEPTH_SIZE, 0 },
{ EGL_CONFIG_ID, 6 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
@@ -981,6 +984,7 @@
{ EGL_RED_SIZE, 8 },
{ EGL_DEPTH_SIZE, 16 },
{ EGL_CONFIG_ID, 7 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
@@ -993,6 +997,7 @@
{ EGL_RED_SIZE, 8 },
{ EGL_DEPTH_SIZE, 0 },
{ EGL_CONFIG_ID, 2 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
@@ -1004,6 +1009,7 @@
{ EGL_RED_SIZE, 8 },
{ EGL_DEPTH_SIZE, 16 },
{ EGL_CONFIG_ID, 3 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
@@ -1016,6 +1022,7 @@
{ EGL_RED_SIZE, 0 },
{ EGL_DEPTH_SIZE, 0 },
{ EGL_CONFIG_ID, 4 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
@@ -1027,6 +1034,7 @@
{ EGL_RED_SIZE, 0 },
{ EGL_DEPTH_SIZE, 16 },
{ EGL_CONFIG_ID, 5 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
{ EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp
index a0f720a..8b4136a 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -33,7 +33,7 @@
// ----------------------------------------------------------------------------
static char const * const gVendorString = "Android";
-static char const * const gRendererString = "Android PixelFlinger 1.3";
+static char const * const gRendererString = "Android PixelFlinger 1.4";
static char const * const gVersionString = "OpenGL ES-CM 1.0";
static char const * const gExtensionsString =
"GL_OES_byte_coordinates " // OK
diff --git a/opengl/tests/configdump/Android.mk b/opengl/tests/configdump/Android.mk
new file mode 100644
index 0000000..3f7c915
--- /dev/null
+++ b/opengl/tests/configdump/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ configdump.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libEGL \
+ libGLESv1_CM
+
+LOCAL_MODULE:= test-opengl-configdump
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/configdump/configdump.cpp b/opengl/tests/configdump/configdump.cpp
new file mode 100644
index 0000000..69b9eb6
--- /dev/null
+++ b/opengl/tests/configdump/configdump.cpp
@@ -0,0 +1,89 @@
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+
+#define ATTRIBUTE(_attr) { _attr, #_attr }
+
+struct Attribute {
+ EGLint attribute;
+ char const* name;
+};
+
+Attribute attributes[] = {
+ ATTRIBUTE( EGL_BUFFER_SIZE ),
+ ATTRIBUTE( EGL_ALPHA_SIZE ),
+ ATTRIBUTE( EGL_BLUE_SIZE ),
+ ATTRIBUTE( EGL_GREEN_SIZE ),
+ ATTRIBUTE( EGL_RED_SIZE ),
+ ATTRIBUTE( EGL_DEPTH_SIZE ),
+ ATTRIBUTE( EGL_STENCIL_SIZE ),
+ ATTRIBUTE( EGL_CONFIG_CAVEAT ),
+ ATTRIBUTE( EGL_CONFIG_ID ),
+ ATTRIBUTE( EGL_LEVEL ),
+ ATTRIBUTE( EGL_MAX_PBUFFER_HEIGHT ),
+ ATTRIBUTE( EGL_MAX_PBUFFER_WIDTH ),
+ ATTRIBUTE( EGL_MAX_PBUFFER_PIXELS ),
+ ATTRIBUTE( EGL_NATIVE_RENDERABLE ),
+ ATTRIBUTE( EGL_NATIVE_VISUAL_ID ),
+ ATTRIBUTE( EGL_NATIVE_VISUAL_TYPE ),
+ ATTRIBUTE( EGL_SAMPLES ),
+ ATTRIBUTE( EGL_SAMPLE_BUFFERS ),
+ ATTRIBUTE( EGL_SURFACE_TYPE ),
+ ATTRIBUTE( EGL_TRANSPARENT_TYPE ),
+ ATTRIBUTE( EGL_TRANSPARENT_BLUE_VALUE ),
+ ATTRIBUTE( EGL_TRANSPARENT_GREEN_VALUE ),
+ ATTRIBUTE( EGL_TRANSPARENT_RED_VALUE ),
+ ATTRIBUTE( EGL_BIND_TO_TEXTURE_RGB ),
+ ATTRIBUTE( EGL_BIND_TO_TEXTURE_RGBA ),
+ ATTRIBUTE( EGL_MIN_SWAP_INTERVAL ),
+ ATTRIBUTE( EGL_MAX_SWAP_INTERVAL ),
+ ATTRIBUTE( EGL_LUMINANCE_SIZE ),
+ ATTRIBUTE( EGL_ALPHA_MASK_SIZE ),
+ ATTRIBUTE( EGL_COLOR_BUFFER_TYPE ),
+ ATTRIBUTE( EGL_RENDERABLE_TYPE ),
+ ATTRIBUTE( EGL_MATCH_NATIVE_PIXMAP ),
+ ATTRIBUTE( EGL_CONFORMANT ),
+};
+
+
+int main(int argc, char** argv)
+{
+ EGLConfig* configs;
+ EGLint n;
+
+ EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(dpy, 0, 0);
+ eglGetConfigs(dpy, NULL, 0, &n);
+ configs = new EGLConfig[n];
+ eglGetConfigs(dpy, configs, n, &n);
+
+ for (EGLint i=0 ; i<n ; i++) {
+ printf("EGLConfig[%d]\n", i);
+ for (int attr = 0 ; attr<sizeof(attributes)/sizeof(Attribute) ; attr++) {
+ EGLint value;
+ eglGetConfigAttrib(dpy, configs[i], attributes[attr].attribute, &value);
+ printf("\t%-32s: %10d (0x%08x)\n", attributes[attr].name, value, value);
+ }
+ }
+
+ delete [] configs;
+ eglTerminate(dpy);
+ return 0;
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 5fde3c3..d824f30 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -14,15 +14,13 @@
android:allowClearUserData="false"
android:label="@string/app_label"
android:icon="@drawable/ic_launcher_settings">
-
- <service
- android:name=".statusbar.PhoneStatusBarService"
- android:exported="false"
- />
- <service
- android:name=".statusbar.tablet.TabletStatusBarService"
- android:exported="false"
+ <!-- Broadcast receiver that gets the broadcast at boot time and starts
+ up everything else.
+ TODO: Should have an android:permission attribute
+ -->
+ <service android:name="SystemUIService"
+ android:exported="true"
/>
<activity android:name=".usb.UsbStorageActivity"
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket.png
new file mode 100644
index 0000000..90dffa9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_drag.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_drag.png
new file mode 100644
index 0000000..dcce495
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_drag.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_hidden.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_hidden.png
new file mode 100644
index 0000000..93b0d23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_hidden.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_holding.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_holding.png
new file mode 100644
index 0000000..9eb9dc6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_pocket_holding.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index 295c79b..8824028 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -34,7 +34,6 @@
android:src="@drawable/ic_sysbar_open"
android:background="@drawable/ic_sysbar_icon_bg"
android:paddingLeft="6dip"
- android:onClick="notificationIconsClicked"
/>
<LinearLayout
@@ -136,6 +135,27 @@
android:layout_alignParentRight="true"
android:orientation="horizontal"
>
+ <com.android.systemui.statusbar.tablet.ShirtPocket
+ android:id="@+id/pocket"
+ android:layout_width="71dip"
+ android:layout_height="match_parent"
+ android:background="@drawable/ic_sysbar_icon_bg"
+ android:paddingLeft="4dip"
+ android:paddingRight="4dip"
+ android:animateLayoutChanges="true"
+ android:clickable="true"
+ android:descendantFocusability="blocksDescendants"
+ android:gravity="center"
+ >
+ <ImageView
+ android:id="@+id/pocket_icon"
+ android:src="@drawable/ic_sysbar_pocket"
+ android:visibility="invisible"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ />
+ </com.android.systemui.statusbar.tablet.ShirtPocket>
<com.android.systemui.statusbar.KeyButtonView android:id="@+id/menu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
@@ -153,7 +173,6 @@
android:background="@drawable/ic_sysbar_icon_bg"
android:paddingLeft="4dip"
android:paddingRight="4dip"
- android:onClick="recentButtonClicked"
/>
<com.android.systemui.statusbar.KeyButtonView android:id="@+id/home"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_center.xml b/packages/SystemUI/res/layout-xlarge/status_bar_center.xml
index 2d74672..d4f0e50 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_center.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_center.xml
@@ -22,7 +22,6 @@
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:clickable="true"
- android:onClick="systemInfoClicked"
>
<com.android.systemui.statusbar.Clock
style="@*android:style/TextAppearance.StatusBar.Icon"
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_pocket.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_pocket.xml
new file mode 100644
index 0000000..e4a6da4
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_pocket.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="@*android:drawable/dialog_full_holo_dark"
+ >
+ <TextView
+ android:id="@+id/description"
+ android:textAppearance="@android:style/TextAppearance.Small"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textStyle="bold"
+ android:maxLines="1"
+ android:layout_alignParentBottom="true"
+ />
+
+ <FrameLayout
+ android:id="@+id/preview"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_above="@+id/description"
+ android:descendantFocusability="blocksDescendants"
+ >
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:visibility="gone"
+ />
+ <TextView
+ android:id="@+id/alt"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:textAppearance="@android:style/TextAppearance.Large"
+ android:gravity="center"
+ android:visibility="gone"
+ />
+ </FrameLayout>
+</RelativeLayout>
diff --git a/packages/SystemUI/res/values-xlarge/config.xml b/packages/SystemUI/res/values-xlarge/config.xml
index 4cf5d18d11..6df883c 100644
--- a/packages/SystemUI/res/values-xlarge/config.xml
+++ b/packages/SystemUI/res/values-xlarge/config.xml
@@ -21,5 +21,10 @@
for different hardware and product builds. -->
<resources>
<integer name="config_status_bar_position">1</integer>
+
+ <!-- Component to be used as the status bar service. Must implement the IStatusBar
+ interface. This name is in the ComponentName flattened format (package/class) -->
+ <string name="config_statusBarComponent">com.android.systemui.statusbar.tablet.TabletStatusBarService</string>
+
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index ac00c69..4570d8e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -31,5 +31,9 @@
-->
<integer name="config_status_bar_position">0</integer>
+ <!-- Component to be used as the status bar service. Must implement the IStatusBar
+ interface. This name is in the ComponentName flattened format (package/class) -->
+ <string name="config_statusBarComponent">com.android.systemui.statusbar.PhoneStatusBarService</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
new file mode 100644
index 0000000..53fe2ff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import android.content.Context;
+
+public abstract class SystemUI {
+ public Context mContext;
+
+ public abstract void start();
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
new file mode 100644
index 0000000..dda86d2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Slog;
+
+public class SystemUIService extends Service {
+ static final String TAG = "SystemUIService";
+
+ /**
+ * The class names of the stuff to start.
+ */
+ final Object[] SERVICES = new Object[] {
+ R.string.config_statusBarComponent,
+ };
+
+ /**
+ * Hold a reference on the stuff we start.
+ */
+ SystemUI[] mServices;
+
+ private Class chooseClass(Object o) {
+ if (o instanceof Integer) {
+ final String cl = getString((Integer)o);
+ try {
+ return getClassLoader().loadClass(cl);
+ } catch (ClassNotFoundException ex) {
+ throw new RuntimeException(ex);
+ }
+ } else if (o instanceof Class) {
+ return (Class)o;
+ } else {
+ throw new RuntimeException("Unknown system ui service: " + o);
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ final int N = SERVICES.length;
+ mServices = new SystemUI[N];
+ for (int i=0; i<N; i++) {
+ Class cl = chooseClass(SERVICES[i]);
+ Slog.d(TAG, "loading: " + cl);
+ try {
+ mServices[i] = (SystemUI)cl.newInstance();
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ } catch (InstantiationException ex) {
+ throw new RuntimeException(ex);
+ }
+ mServices[i].mContext = this;
+ Slog.d(TAG, "running: " + mServices[i]);
+ mServices[i].start();
+ }
+ }
+
+ /**
+ * Nobody binds to us.
+ */
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump StatusBar from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ for (SystemUI ui: mServices) {
+ pw.println("dumping service: " + ui.getClass().getName());
+ ui.dump(fd, pw, args);
+ }
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index fc7b534..bf58b37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -27,7 +27,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -35,7 +34,6 @@
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.Binder;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
@@ -195,27 +193,23 @@
}
@Override
- public void onCreate() {
- mDisplay = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+ public void start() {
+ mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay();
- super.onCreate();
+ super.start();
addIntruderView();
// Lastly, call to the icon policy to install/update all the icons.
- mIconPolicy = new StatusBarPolicy(this);
- }
-
- @Override
- public void onDestroy() {
- // we're never destroyed
+ mIconPolicy = new StatusBarPolicy(mContext);
}
// ================================================================================
// Constructing the view
// ================================================================================
protected View makeStatusBarView() {
- final Context context = this;
+ final Context context = mContext;
Resources res = context.getResources();
@@ -293,7 +287,7 @@
}
private void addIntruderView() {
- final Resources res = getResources();
+ final Resources res = mContext.getResources();
final int height= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
@@ -317,7 +311,7 @@
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ " icon=" + icon);
- StatusBarIconView view = new StatusBarIconView(this, slot);
+ StatusBarIconView view = new StatusBarIconView(mContext, slot);
view.set(icon);
mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
}
@@ -434,7 +428,7 @@
oldEntry.notification = notification;
try {
// Reapply the RemoteViews
- contentView.reapply(this, oldEntry.content);
+ contentView.reapply(mContext, oldEntry.content);
// update the contentIntent
final PendingIntent contentIntent = notification.notification.contentIntent;
if (contentIntent != null) {
@@ -507,7 +501,8 @@
}
// create the row view
- LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.status_bar_latest_event, parent, false);
// bind the click event to the content area
@@ -525,7 +520,7 @@
View expanded = null;
Exception exception = null;
try {
- expanded = remoteViews.apply(this, content);
+ expanded = remoteViews.apply(mContext, content);
}
catch (RuntimeException e) {
exception = e;
@@ -564,7 +559,7 @@
final View content = views[1];
final View expanded = views[2];
// Construct the icon.
- final StatusBarIconView iconView = new StatusBarIconView(this,
+ final StatusBarIconView iconView = new StatusBarIconView(mContext,
notification.pkg + "/0x" + Integer.toHexString(notification.id));
final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon,
notification.notification.iconLevel, notification.notification.number);
@@ -1050,7 +1045,7 @@
overlay.setSourceBounds(
new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
try {
- mIntent.send(PhoneStatusBarService.this, 0, overlay);
+ mIntent.send(mContext, 0, overlay);
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here. Just log the exception message.
Slog.w(TAG, "Sending contentIntent failed: " + e);
@@ -1151,7 +1146,7 @@
};
private Animation loadAnim(int id, Animation.AnimationListener listener) {
- Animation anim = AnimationUtils.loadAnimation(PhoneStatusBarService.this, id);
+ Animation anim = AnimationUtils.loadAnimation(mContext, id);
if (listener != null) {
anim.setAnimationListener(listener);
}
@@ -1163,15 +1158,7 @@
+ " " + v.getWidth() + "x" + v.getHeight() + ")";
}
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump StatusBar from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mQueueLock) {
pw.println("Current Status Bar state:");
pw.println(" mExpanded=" + mExpanded
@@ -1519,12 +1506,13 @@
* meantime, just update the things that we know change.
*/
void updateResources() {
- Resources res = getResources();
+ final Context context = mContext;
+ final Resources res = context.getResources();
- mClearButton.setText(getText(R.string.status_bar_clear_all_button));
- mOngoingTitle.setText(getText(R.string.status_bar_ongoing_events_title));
- mLatestTitle.setText(getText(R.string.status_bar_latest_events_title));
- mNoNotificationsTitle.setText(getText(R.string.status_bar_no_notifications_title));
+ mClearButton.setText(context.getText(R.string.status_bar_clear_all_button));
+ mOngoingTitle.setText(context.getText(R.string.status_bar_ongoing_events_title));
+ mLatestTitle.setText(context.getText(R.string.status_bar_latest_events_title));
+ mNoNotificationsTitle.setText(context.getText(R.string.status_bar_no_notifications_title));
mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
@@ -1540,7 +1528,8 @@
}
void vibrate() {
- android.os.Vibrator vib = (android.os.Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
+ android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService(
+ Context.VIBRATOR_SERVICE);
vib.vibrate(250);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
index e0019b5..fb74e70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
@@ -699,7 +699,6 @@
NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra(
ConnectivityManager.EXTRA_NETWORK_INFO));
int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
- Slog.d(TAG, "got CONNECTIVITY_ACTION - info=" + info + ", status = " + connectionStatus);
int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index 5594a47..ae1fdbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -40,10 +40,12 @@
import com.android.internal.statusbar.StatusBarIconList;
import com.android.internal.statusbar.StatusBarNotification;
+import com.android.systemui.SystemUI;
import com.android.systemui.R;
-public abstract class StatusBarService extends Service implements CommandQueue.Callbacks {
+public abstract class StatusBarService extends SystemUI implements CommandQueue.Callbacks {
static final String TAG = "StatusBarService";
+ private static final boolean SPEW = false;
protected CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
@@ -52,16 +54,7 @@
protected abstract View makeStatusBarView();
protected abstract int getStatusBarGravity();
- /**
- * Nobody binds to us.
- */
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public void onCreate() {
+ public void start() {
// First set up our views and stuff.
View sb = makeStatusBarView();
@@ -106,7 +99,7 @@
}
// Put up the view
- final Resources res = getResources();
+ final Resources res = mContext.getResources();
final int height= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
@@ -121,11 +114,12 @@
// TODO lp.windowAnimations = R.style.Animation_StatusBar;
WindowManagerImpl.getDefault().addView(sb, lp);
- Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity)
- + " icons=" + iconList.size()
- + " lights=" + (switches[0]?"on":"off")
- + " menu=" + (switches[1]?"visible":"invisible")
- );
+ if (SPEW) {
+ Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity)
+ + " icons=" + iconList.size()
+ + " lights=" + (switches[0]?"on":"off")
+ + " menu=" + (switches[1]?"visible":"invisible")
+ );
+ }
}
}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
new file mode 100644
index 0000000..658038c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tablet;
+
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.util.Slog;
+import android.view.View;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.view.DragEvent;
+import android.view.MotionEvent;
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.graphics.Paint;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Point;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.view.WindowManagerImpl;
+import android.graphics.PixelFormat;
+import android.view.Gravity;
+
+import com.android.systemui.R;
+
+public class ShirtPocket extends FrameLayout {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "StatusBar/ShirtPocket";
+
+ private ClipData mClipping = null;
+
+ private View mWindow = null;
+ private ImageView mIcon;
+ private ImageView mPreviewIcon;
+ private TextView mDescription;
+ private TextView mAltText;
+
+ public ShirtPocket(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setupWindow();
+ }
+
+ // TODO: "pin area" panel, dragging things out
+ ObjectAnimator mAnimHide, mAnimShow;
+
+ protected void onAttachedToWindow() {
+ // Drag API notes: we must be visible to receive drag events
+ setVisibility(View.VISIBLE);
+
+ mIcon = (ImageView) findViewById(R.id.pocket_icon);
+ refreshStatusIcon();
+
+ setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ if (mClipping != null) {
+ if (mWindow.getVisibility() == View.VISIBLE) hideWindow();
+ else showWindow();
+ }
+ }
+ });
+ }
+
+ private void refreshStatusIcon() {
+ setClickable(mClipping != null);
+ mIcon.setImageResource(mClipping == null
+ ? R.drawable.ic_sysbar_pocket_hidden
+ : R.drawable.ic_sysbar_pocket_holding);
+ mIcon.setVisibility(mClipping == null ? View.INVISIBLE : View.VISIBLE);
+ }
+
+ private void showWindow() {
+ getHandler().post(new Runnable() {
+ public void run() {
+ mWindow.setVisibility(View.VISIBLE);
+ refreshStatusIcon();
+ }
+ });
+ }
+
+ private void hideWindow() {
+ getHandler().post(new Runnable() {
+ public void run() {
+ mWindow.setVisibility(View.GONE);
+ refreshStatusIcon();
+ }
+ });
+ }
+
+ private void hideWindowInJustASec() {
+ getHandler().postDelayed(new Runnable() {
+ public void run() {
+ mWindow.setVisibility(View.GONE);
+ refreshStatusIcon();
+ }
+ },
+ 250);
+ }
+
+ private void stash(ClipData clipping) {
+ mClipping = clipping;
+ if (mClipping != null) {
+ Bitmap icon = mClipping.getIcon();
+ mDescription.setText(mClipping.getLabel());
+ if (icon != null) {
+ mPreviewIcon.setImageBitmap(icon);
+ mPreviewIcon.setVisibility(View.VISIBLE);
+ mAltText.setVisibility(View.GONE);
+ } else {
+ mPreviewIcon.setVisibility(View.GONE);
+ mAltText.setVisibility(View.VISIBLE);
+ if (mClipping.getItemCount() > 0) {
+ // TODO: figure out how to visualize every kind of ClipData!
+ mAltText.setText(mClipping.getItem(0).coerceToText(getContext()));
+ }
+ }
+ }
+ }
+
+ private boolean isInViewContentArea(View v, int x, int y) {
+ final int l = v.getPaddingLeft();
+ final int r = v.getWidth() - v.getPaddingRight();
+ final int t = v.getPaddingTop();
+ final int b = v.getHeight() - v.getPaddingBottom();
+ return x >= l && x < r && y >= t && y < b;
+ }
+
+ View.OnTouchListener mWindowTouchListener = new View.OnTouchListener() {
+ public boolean onTouch(View v, MotionEvent ev) {
+ final int action = ev.getAction();
+ if (action == MotionEvent.ACTION_OUTSIDE
+ || (action == MotionEvent.ACTION_DOWN
+ && !isInViewContentArea(mWindow, (int)ev.getX(), (int)ev.getY()))) {
+ hideWindow();
+ return true;
+ } else if (action == MotionEvent.ACTION_DOWN) {
+ Slog.d(TAG, "ACTION_DOWN");
+ final ClipData clip = mClipping;
+ if (clip != null) {
+ final Bitmap icon = clip.getIcon();
+ DragThumbnailBuilder thumb;
+ if (icon != null) {
+ thumb = new DragThumbnailBuilder(v) {
+ public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
+ thumbnailSize.set(icon.getWidth(), icon.getHeight());
+ thumbnailTouchPoint.set(thumbnailSize.x / 2, thumbnailSize.y / 2);
+ }
+ public void onDrawThumbnail(Canvas canvas) {
+ canvas.drawBitmap(icon, 0, 0, new Paint());
+ }
+ };
+ } else {
+ // uhhh, what now?
+ thumb = new DragThumbnailBuilder(mWindow.findViewById(R.id.preview));
+ }
+
+ ShirtPocket.this.startDrag(clip, thumb, false);
+
+ // TODO: only discard the clipping if it was accepted
+ stash(null);
+
+ hideWindowInJustASec(); // will refresh the icon
+
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+ private void setupWindow() {
+ mWindow = View.inflate(getContext(), R.layout.sysbar_panel_pocket, null);
+
+ mPreviewIcon = (ImageView) mWindow.findViewById(R.id.icon);
+ mDescription = (TextView) mWindow.findViewById(R.id.description);
+ mAltText = (TextView) mWindow.findViewById(R.id.alt);
+
+ mWindow.setVisibility(View.GONE);
+ mWindow.setOnTouchListener(mWindowTouchListener);
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ 400,
+ 250,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ PixelFormat.TRANSLUCENT);
+ lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+// int pos[] = new int[2];
+// getLocationOnScreen(pos);
+// lp.x = pos[1];
+// lp.y = 0;
+ lp.setTitle("ShirtPocket");
+ lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
+
+ WindowManagerImpl.getDefault().addView(mWindow, lp);
+
+ }
+
+ public boolean onDragEvent(DragEvent event) {
+ if (DEBUG) Slog.d(TAG, "onDragEvent: " + event);
+ if (mIcon != null) {
+ switch (event.getAction()) {
+ // We want to appear whenever a potential drag takes off from anywhere in the UI.
+ case DragEvent.ACTION_DRAG_STARTED:
+ mIcon.setImageResource(mClipping == null
+ ? R.drawable.ic_sysbar_pocket
+ : R.drawable.ic_sysbar_pocket_holding);
+ mIcon.setVisibility(View.VISIBLE);
+ break;
+ case DragEvent.ACTION_DRAG_ENTERED:
+ if (DEBUG) Slog.d(TAG, "entered!");
+ mIcon.setImageResource(R.drawable.ic_sysbar_pocket_drag);
+ break;
+ case DragEvent.ACTION_DRAG_EXITED:
+ if (DEBUG) Slog.d(TAG, "exited!");
+ mIcon.setImageResource(mClipping == null
+ ? R.drawable.ic_sysbar_pocket
+ : R.drawable.ic_sysbar_pocket_holding);
+ break;
+ case DragEvent.ACTION_DROP:
+ if (DEBUG) Slog.d(TAG, "dropped!");
+ stash(event.getClipData());
+ refreshStatusIcon();
+ break;
+ case DragEvent.ACTION_DRAG_ENDED:
+ refreshStatusIcon();
+ break;
+ }
+ }
+ return true; // we want everything, thank you
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 340e269..6426e7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.tablet;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
import android.app.ActivityManagerNative;
import android.app.PendingIntent;
import android.app.Notification;
@@ -80,6 +83,7 @@
View mSystemInfo;
View mNavigationArea;
View mMenuButton;
+ View mRecentButton;
NotificationPanel mNotificationPanel;
SystemPanel mSystemPanel;
@@ -107,11 +111,13 @@
boolean mNotificationsOn = true;
protected void addPanelWindows() {
- final Resources res = getResources();
+ final Context context = mContext;
+
+ final Resources res = context.getResources();
final int barHeight= res.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
- mNotificationPanel = (NotificationPanel)View.inflate(this,
+ mNotificationPanel = (NotificationPanel)View.inflate(context,
R.layout.sysbar_panel_notifications, null);
mNotificationPanel.setVisibility(View.GONE);
mNotificationPanel.setOnTouchListener(
@@ -132,7 +138,7 @@
WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
- mSystemPanel = (SystemPanel) View.inflate(this, R.layout.sysbar_panel_system, null);
+ mSystemPanel = (SystemPanel) View.inflate(context, R.layout.sysbar_panel_system, null);
mSystemPanel.setVisibility(View.GONE);
mSystemPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_SYSTEM_PANEL,
mSystemPanel));
@@ -155,17 +161,18 @@
}
@Override
- public void onCreate() {
- super.onCreate(); // will add the main bar view
+ public void start() {
+ super.start(); // will add the main bar view
}
protected View makeStatusBarView() {
- Resources res = getResources();
+ final Context context = mContext;
+ final Resources res = context.getResources();
mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
- this, R.layout.status_bar, null);
+ context, R.layout.status_bar, null);
mStatusBarView = sb;
sb.setHandler(mHandler);
@@ -174,14 +181,19 @@
mCurtains = sb.findViewById(R.id.lights_out);
mSystemInfo = sb.findViewById(R.id.systemInfo);
+ mSystemInfo.setOnClickListener(mOnClickListener);
mSystemInfo.setOnLongClickListener(new SetLightsOnListener(false));
+ mRecentButton = sb.findViewById(R.id.recent);
+ mRecentButton.setOnClickListener(mOnClickListener);
+
SetLightsOnListener on = new SetLightsOnListener(true);
mCurtains.setOnClickListener(on);
mCurtains.setOnLongClickListener(on);
// the button to open the notification area
mNotificationTrigger = sb.findViewById(R.id.expand);
+ mNotificationTrigger.setOnClickListener(mOnClickListener);
// the more notifications icon
mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
@@ -189,15 +201,15 @@
// the clear and dnd buttons
mNotificationButtons = sb.findViewById(R.id.notificationButtons);
mClearButton = (TextView)mNotificationButtons.findViewById(R.id.clear_all_button);
- mClearButton.setOnClickListener(mClearButtonListener);
+ mClearButton.setOnClickListener(mOnClickListener);
mDoNotDisturbButton = (TextView)mNotificationButtons.findViewById(R.id.do_not_disturb);
- mDoNotDisturbButton.setOnClickListener(mDoNotDisturbButtonListener);
+ mDoNotDisturbButton.setOnClickListener(mOnClickListener);
// where the icons go
mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
- mTicker = new TabletTicker((Context)this, (FrameLayout)sb.findViewById(R.id.ticker));
+ mTicker = new TabletTicker(context, (FrameLayout)sb.findViewById(R.id.ticker));
// System info (center)
mBatteryMeter = (ImageView) sb.findViewById(R.id.battery);
@@ -366,7 +378,7 @@
oldEntry.notification = notification;
try {
// Reapply the RemoteViews
- contentView.reapply(this, oldEntry.content);
+ contentView.reapply(mContext, oldEntry.content);
// update the contentIntent
final PendingIntent contentIntent = notification.notification.contentIntent;
if (contentIntent != null) {
@@ -551,37 +563,6 @@
*/
}
- public void notificationIconsClicked(View v) {
- if (DEBUG) Slog.d(TAG, "clicked notification icons");
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
- int msg = (mNotificationPanel.getVisibility() == View.GONE)
- ? MSG_OPEN_NOTIFICATION_PANEL
- : MSG_CLOSE_NOTIFICATION_PANEL;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
- }
- }
-
- public void systemInfoClicked(View v) {
- if (DEBUG) Slog.d(TAG, "clicked system info");
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
- int msg = (mSystemPanel.getVisibility() == View.GONE)
- ? MSG_OPEN_SYSTEM_PANEL
- : MSG_CLOSE_SYSTEM_PANEL;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
- }
- }
-
- public void recentButtonClicked(View v) {
- if (DEBUG) Slog.d(TAG, "clicked recent apps");
- Intent intent = new Intent();
- intent.setClass(this, RecentApplicationsActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- startActivity(intent);
- }
-
/**
* Cancel this notification and tell the status bar service about the failure. Hold no locks.
*/
@@ -594,23 +575,66 @@
}
}
- private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
+ private View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) {
- try {
- mBarService.onClearAllNotifications();
- } catch (RemoteException ex) {
- // system process is dead if we're here.
+ if (v == mClearButton) {
+ onClickClearButton();
+ } else if (v == mDoNotDisturbButton) {
+ onClickDoNotDisturb();
+ } else if (v == mNotificationTrigger) {
+ onClickNotificationTrigger();
+ } else if (v == mSystemInfo) {
+ onClickSystemInfo();
+ } else if (v == mRecentButton) {
+ onClickRecentButton();
}
- animateCollapse();
}
};
- private View.OnClickListener mDoNotDisturbButtonListener = new View.OnClickListener() {
- public void onClick(View v) {
- mNotificationsOn = !mNotificationsOn;
- animateCollapse();
+ void onClickClearButton() {
+ try {
+ mBarService.onClearAllNotifications();
+ } catch (RemoteException ex) {
+ // system process is dead if we're here.
}
- };
+ animateCollapse();
+ }
+
+ void onClickDoNotDisturb() {
+ mNotificationsOn = !mNotificationsOn;
+ animateCollapse();
+ }
+
+ public void onClickNotificationTrigger() {
+ if (DEBUG) Slog.d(TAG, "clicked notification icons");
+ if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
+ int msg = (mNotificationPanel.getVisibility() == View.GONE)
+ ? MSG_OPEN_NOTIFICATION_PANEL
+ : MSG_CLOSE_NOTIFICATION_PANEL;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+ }
+
+ public void onClickSystemInfo() {
+ if (DEBUG) Slog.d(TAG, "clicked system info");
+ if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
+ int msg = (mSystemPanel.getVisibility() == View.GONE)
+ ? MSG_OPEN_SYSTEM_PANEL
+ : MSG_CLOSE_SYSTEM_PANEL;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
+ }
+
+ public void onClickRecentButton() {
+ if (DEBUG) Slog.d(TAG, "clicked recent apps");
+ Intent intent = new Intent();
+ intent.setClass(mContext, RecentApplicationsActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ mContext.startActivity(intent);
+ }
private class NotificationClicker implements View.OnClickListener {
private PendingIntent mIntent;
@@ -642,7 +666,7 @@
overlay.setSourceBounds(
new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
try {
- mIntent.send(TabletStatusBarService.this, 0, overlay);
+ mIntent.send(mContext, 0, overlay);
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here. Just log the exception message.
Slog.w(TAG, "Sending contentIntent failed: " + e);
@@ -685,7 +709,7 @@
Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
}
// Construct the icon.
- final StatusBarIconView iconView = new StatusBarIconView(this,
+ final StatusBarIconView iconView = new StatusBarIconView(mContext,
notification.pkg + "/0x" + Integer.toHexString(notification.id));
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
@@ -743,7 +767,8 @@
}
// create the row view
- LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.status_bar_latest_event, parent, false);
View vetoButton = row.findViewById(R.id.veto);
if (entry.notification.isClearable()) {
@@ -780,7 +805,7 @@
View expanded = null;
Exception exception = null;
try {
- expanded = remoteViews.apply(this, content);
+ expanded = remoteViews.apply(mContext, content);
}
catch (RuntimeException e) {
exception = e;
@@ -853,10 +878,16 @@
private void setViewVisibility(View v, int vis, int anim) {
if (v.getVisibility() != vis) {
//Slog.d(TAG, "setViewVisibility vis=" + (vis == View.VISIBLE) + " v=" + v);
- v.setAnimation(AnimationUtils.loadAnimation((Context)this, anim));
+ v.setAnimation(AnimationUtils.loadAnimation(mContext, anim));
v.setVisibility(vis);
}
}
+
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print("mDisabled=0x");
+ pw.println(Integer.toHexString(mDisabled));
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index d19f318..165107c 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -97,8 +97,8 @@
public class KeyguardViewMediator implements KeyguardViewCallback,
KeyguardUpdateMonitor.SimStateCallback {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
- private final static boolean DEBUG = false && Config.LOGD;
- private final static boolean DBG_WAKE = DEBUG || true;
+ private final static boolean DEBUG = false;
+ private final static boolean DBG_WAKE = false;
private final static String TAG = "KeyguardViewMediator";
@@ -642,7 +642,7 @@
* @see #onWakeKeyWhenKeyguardShowingTq(int)
*/
private void wakeWhenReadyLocked(int keyCode) {
- if (DBG_WAKE) Log.d(TAG, "wakeWhenReadyLocked(" + keyCode + ")");
+ if (true || DBG_WAKE) Log.d(TAG, "wakeWhenReadyLocked(" + keyCode + ")");
/**
* acquire the handoff lock that will keep the cpu running. this will
@@ -1169,5 +1169,3 @@
}
}
}
-
-
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 50b3abe..90ebf3f 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -664,11 +664,11 @@
// backup.
RandomAccessFile in = null;
try {
- Slog.i(TAG, "Found stale backup journal, scheduling:");
+ Slog.i(TAG, "Found stale backup journal, scheduling");
in = new RandomAccessFile(f, "r");
while (true) {
String packageName = in.readUTF();
- Slog.i(TAG, " + " + packageName);
+ Slog.i(TAG, " " + packageName);
dataChangedImpl(packageName);
}
} catch (EOFException e) {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 15eaa9e..8066fa7 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -700,9 +700,6 @@
public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
String tag, int id, Notification notification, int[] idOut)
{
- Slog.d(TAG, "enqueueNotificationWithTag: calling uid=" + callingUid
- + ", pid=" + callingPid);
-
checkIncomingCall(pkg);
// Limit the number of notifications that any given package except the android
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 666bb26..c50a01e 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2500,7 +2500,9 @@
return;
}
- Log.d(TAG, "Scanning app dir " + dir);
+ if (false) {
+ Log.d(TAG, "Scanning app dir " + dir);
+ }
int i;
for (i=0; i<files.length; i++) {
@@ -2866,10 +2868,8 @@
TAG, "Scanning package " + pkg.packageName);
if (mPackages.containsKey(pkg.packageName)
|| mSharedLibraries.containsKey(pkg.packageName)) {
- Slog.w(TAG, "*************************************************");
Slog.w(TAG, "Application package " + pkg.packageName
+ " already installed. Skipping duplicate.");
- Slog.w(TAG, "*************************************************");
mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
return null;
}
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 66e02146..400b31f 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -54,7 +54,7 @@
public class StatusBarManagerService extends IStatusBarService.Stub
{
static final String TAG = "StatusBarManagerService";
- static final boolean SPEW = true;
+ static final boolean SPEW = false;
final Context mContext;
Handler mHandler = new Handler();
@@ -111,22 +111,6 @@
}
// ================================================================================
- // Constructing the view
- // ================================================================================
-
- public void systemReady() {
- }
-
- public void systemReady2() {
- ComponentName cn = ComponentName.unflattenFromString(
- mContext.getString(com.android.internal.R.string.config_statusBarComponent));
- Intent intent = new Intent();
- intent.setComponent(cn);
- Slog.i(TAG, "Starting service: " + cn);
- mContext.startService(intent);
- }
-
- // ================================================================================
// From IStatusBarService
// ================================================================================
public void expand() {
@@ -161,7 +145,6 @@
synchronized (mDisableRecords) {
manageDisableListLocked(what, token, pkg);
final int net = gatherDisableActionsLocked();
- Slog.d(TAG, "disable... net=0x" + Integer.toHexString(net));
if (net != mDisabled) {
mDisabled = net;
mHandler.post(new Runnable() {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ec12e80..46797c5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -27,9 +27,11 @@
import android.accounts.AccountManagerService;
import android.app.ActivityManagerNative;
import android.bluetooth.BluetoothAdapter;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentService;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.res.Configuration;
import android.database.ContentObserver;
@@ -502,9 +504,6 @@
notification.systemReady();
}
- if (statusBar != null) {
- statusBar.systemReady();
- }
wm.systemReady();
// Update the configuration for this context by hand, because we're going
@@ -523,7 +522,7 @@
}
// These are needed to propagate to the runnable below.
- final StatusBarManagerService statusBarF = statusBar;
+ final Context contextF = context;
final BatteryService batteryF = battery;
final ConnectivityService connectivityF = connectivity;
final DockObserver dockF = dock;
@@ -548,7 +547,7 @@
public void run() {
Slog.i(TAG, "Making services ready");
- if (statusBarF != null) statusBarF.systemReady2();
+ startSystemUi(contextF);
if (batteryF != null) batteryF.systemReady();
if (connectivityF != null) connectivityF.systemReady();
if (dockF != null) dockF.systemReady();
@@ -578,6 +577,14 @@
Looper.loop();
Slog.d(TAG, "System ServerThread is exiting!");
}
+
+ static final void startSystemUi(Context context) {
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName("com.android.systemui",
+ "com.android.systemui.SystemUIService"));
+ Slog.d(TAG, "Starting service: " + intent);
+ context.startService(intent);
+ }
}
public class SystemServer {
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 2b4845b..f5b7ca9 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -65,7 +65,9 @@
private final Context mContext;
- private final ArrayList<Record> mRecords = new ArrayList();
+ // access should be inside synchronized (mRecords) for these two fields
+ private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
+ private final ArrayList<Record> mRecords = new ArrayList<Record>();
private final IBatteryStats mBatteryStats;
@@ -158,7 +160,11 @@
r.events = events;
if (notifyNow) {
if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
- sendServiceState(r, mServiceState);
+ try {
+ r.callback.onServiceStateChanged(new ServiceState(mServiceState));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
@@ -184,7 +190,11 @@
}
}
if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
- sendCellLocation(r, mCellLocation);
+ try {
+ r.callback.onCellLocationChanged(new Bundle(mCellLocation));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
}
if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
try {
@@ -238,7 +248,6 @@
if (!checkNotifyPermission("notifyCallState()")) {
return;
}
- ArrayList<IBinder> removeList = new ArrayList<IBinder>();
synchronized (mRecords) {
mCallState = state;
mCallIncomingNumber = incomingNumber;
@@ -247,11 +256,11 @@
try {
r.callback.onCallStateChanged(state, incomingNumber);
} catch (RemoteException ex) {
- removeList.add(r.binder);
+ mRemoveList.add(r.binder);
}
}
}
- for (IBinder b : removeList) remove(b);
+ handleRemoveListLocked();
}
broadcastCallStateChanged(state, incomingNumber);
}
@@ -260,13 +269,19 @@
if (!checkNotifyPermission("notifyServiceState()")){
return;
}
+ Slog.i(TAG, "notifyServiceState: " + state);
synchronized (mRecords) {
mServiceState = state;
for (Record r : mRecords) {
if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
- sendServiceState(r, state);
+ try {
+ r.callback.onServiceStateChanged(new ServiceState(state));
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
+ handleRemoveListLocked();
}
broadcastServiceStateChanged(state);
}
@@ -275,12 +290,15 @@
if (!checkNotifyPermission("notifySignalStrength()")) {
return;
}
- ArrayList<IBinder> removeList = new ArrayList<IBinder>();
synchronized (mRecords) {
mSignalStrength = signalStrength;
for (Record r : mRecords) {
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
- sendSignalStrength(r, signalStrength);
+ try {
+ r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
@@ -288,11 +306,11 @@
r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
: gsmSignalStrength));
} catch (RemoteException ex) {
- removeList.add(r.binder);
+ mRemoveList.add(r.binder);
}
}
}
- for (IBinder b : removeList) remove(b);
+ handleRemoveListLocked();
}
broadcastSignalStrengthChanged(signalStrength);
}
@@ -301,7 +319,6 @@
if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
return;
}
- ArrayList<IBinder> removeList = new ArrayList<IBinder>();
synchronized (mRecords) {
mMessageWaiting = mwi;
for (Record r : mRecords) {
@@ -309,11 +326,11 @@
try {
r.callback.onMessageWaitingIndicatorChanged(mwi);
} catch (RemoteException ex) {
- removeList.add(r.binder);
+ mRemoveList.add(r.binder);
}
}
}
- for (IBinder b : removeList) remove(b);
+ handleRemoveListLocked();
}
}
@@ -321,7 +338,6 @@
if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
return;
}
- ArrayList<IBinder> removeList = new ArrayList<IBinder>();
synchronized (mRecords) {
mCallForwarding = cfi;
for (Record r : mRecords) {
@@ -329,11 +345,11 @@
try {
r.callback.onCallForwardingIndicatorChanged(cfi);
} catch (RemoteException ex) {
- removeList.add(r.binder);
+ mRemoveList.add(r.binder);
}
}
}
- for (IBinder b : removeList) remove(b);
+ handleRemoveListLocked();
}
}
@@ -341,7 +357,7 @@
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
- ArrayList<IBinder> removeList = new ArrayList<IBinder>();
+ handleRemoveListLocked();
synchronized (mRecords) {
mDataActivity = state;
for (Record r : mRecords) {
@@ -349,11 +365,11 @@
try {
r.callback.onDataActivity(state);
} catch (RemoteException ex) {
- removeList.add(r.binder);
+ mRemoveList.add(r.binder);
}
}
}
- for (IBinder b : removeList) remove(b);
+ handleRemoveListLocked();
}
}
@@ -363,6 +379,9 @@
if (!checkNotifyPermission("notifyDataConnection()" )) {
return;
}
+ Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
+ + isDataConnectivityPossible + " reason=" + reason
+ + " apn=" + apn + " networkType=" + networkType);
synchronized (mRecords) {
boolean modified = false;
if (state == TelephonyManager.DATA_CONNECTED) {
@@ -392,17 +411,16 @@
modified = true;
}
if (modified) {
- ArrayList<IBinder> removeList = new ArrayList<IBinder>();
for (Record r : mRecords) {
if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
try {
r.callback.onDataConnectionStateChanged(state, networkType);
} catch (RemoteException ex) {
- removeList.add(r.binder);
+ mRemoveList.add(r.binder);
}
}
}
- for (IBinder b : removeList) remove(b);
+ handleRemoveListLocked();
}
}
broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
@@ -438,36 +456,15 @@
mCellLocation = cellLocation;
for (Record r : mRecords) {
if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
- sendCellLocation(r, cellLocation);
+ try {
+ r.callback.onCellLocationChanged(new Bundle(cellLocation));
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+
}
}
- }
- }
-
- /**
- * Copy the service state object so they can't mess it up in the local calls
- */
- private void sendServiceState(Record r, ServiceState state) {
- try {
- r.callback.onServiceStateChanged(new ServiceState(state));
- } catch (RemoteException ex) {
- remove(r.binder);
- }
- }
-
- private void sendCellLocation(Record r, Bundle cellLocation) {
- try {
- r.callback.onCellLocationChanged(new Bundle(cellLocation));
- } catch (RemoteException ex) {
- remove(r.binder);
- }
- }
-
- private void sendSignalStrength(Record r, SignalStrength signalStrength) {
- try {
- r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
- } catch (RemoteException ex) {
- remove(r.binder);
+ handleRemoveListLocked();
}
}
@@ -628,4 +625,13 @@
android.Manifest.permission.READ_PHONE_STATE, null);
}
}
+
+ private void handleRemoveListLocked() {
+ if (mRemoveList.size() > 0) {
+ for (IBinder b: mRemoveList) {
+ remove(b);
+ }
+ mRemoveList.clear();
+ }
+ }
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 9cd8fbf..4f75366 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -889,7 +889,9 @@
Settings.System.getInt(mContext.getContentResolver(),
Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0);
if (action.equals(Intent.ACTION_SCREEN_ON)) {
- Slog.d(TAG, "ACTION_SCREEN_ON");
+ if (DBG) {
+ Slog.d(TAG, "ACTION_SCREEN_ON");
+ }
mAlarmManager.cancel(mIdleIntent);
mDeviceIdle = false;
mScreenOff = false;
@@ -899,7 +901,9 @@
mWifiStateMachine.enableRssiPolling(true);
updateWifiState();
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- Slog.d(TAG, "ACTION_SCREEN_OFF");
+ if (DBG) {
+ Slog.d(TAG, "ACTION_SCREEN_OFF");
+ }
mScreenOff = true;
mWifiStateMachine.enableRssiPolling(false);
/*
@@ -916,19 +920,26 @@
// but not as long as we would if connected (below)
// TODO - fix the race conditions and switch back to the immediate turn-off
long triggerTime = System.currentTimeMillis() + (2*60*1000); // 2 min
- Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for 120,000 ms");
+ if (DBG) {
+ Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for 120,000 ms");
+ }
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
// // do not keep Wifi awake when screen is off if Wifi is not associated
// mDeviceIdle = true;
// updateWifiState();
} else {
long triggerTime = System.currentTimeMillis() + idleMillis;
- Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
+ if (DBG) {
+ Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis
+ + "ms");
+ }
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
}
}
} else if (action.equals(ACTION_DEVICE_IDLE)) {
- Slog.d(TAG, "got ACTION_DEVICE_IDLE");
+ if (DBG) {
+ Slog.d(TAG, "got ACTION_DEVICE_IDLE");
+ }
mDeviceIdle = true;
reportStartWorkSource();
updateWifiState();
@@ -941,10 +952,15 @@
* the already-set timer.
*/
int pluggedType = intent.getIntExtra("plugged", 0);
+ if (DBG) {
+ Slog.d(TAG, "ACTION_BATTERY_CHANGED pluggedType: " + pluggedType);
+ }
if (mScreenOff && shouldWifiStayAwake(stayAwakeConditions, mPluggedType) &&
!shouldWifiStayAwake(stayAwakeConditions, pluggedType)) {
long triggerTime = System.currentTimeMillis() + idleMillis;
- Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
+ if (DBG) {
+ Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis + "ms");
+ }
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
}
mPluggedType = pluggedType;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index af2fece..7258729 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -501,6 +501,7 @@
boolean mLocalOnly;
ClipData mData;
ClipDescription mDataDescription;
+ boolean mDragResult;
float mCurrentX, mCurrentY;
float mThumbOffsetX, mThumbOffsetY;
InputChannel mServerChannel, mClientChannel;
@@ -594,7 +595,7 @@
if (mDragInProgress && newWin.isPotentialDragTarget()) {
DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
- desc, null);
+ desc, null, false);
try {
newWin.mClient.dispatchDragEvent(event);
// track each window that we've notified that the drag is starting
@@ -629,25 +630,36 @@
}
}
- void broadcastDragEnded() {
+ void broadcastDragEndedLw() {
if (DEBUG_DRAG) {
Slog.d(TAG, "broadcasting DRAG_ENDED");
}
- DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, 0, 0, null, null);
- synchronized (mWindowMap) {
- for (WindowState ws: mNotifiedWindows) {
- try {
- ws.mClient.dispatchDragEvent(evt);
- } catch (RemoteException e) {
- Slog.w(TAG, "Unable to drag-end window " + ws);
- }
+ DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
+ 0, 0, null, null, mDragResult);
+ for (WindowState ws: mNotifiedWindows) {
+ try {
+ ws.mClient.dispatchDragEvent(evt);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Unable to drag-end window " + ws);
}
- mNotifiedWindows.clear();
- mDragInProgress = false;
}
+ mNotifiedWindows.clear();
+ mDragInProgress = false;
evt.recycle();
}
+ void endDragLw() {
+ mDragState.broadcastDragEndedLw();
+
+ // stop intercepting input
+ mDragState.unregister();
+ mInputMonitor.updateInputWindowsLw();
+
+ // free our resources and drop all the object references
+ mDragState.reset();
+ mDragState = null;
+ }
+
void notifyMoveLw(float x, float y) {
final int myPid = Process.myPid();
@@ -667,7 +679,7 @@
// force DRAG_EXITED_EVENT if appropriate
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
- null, null);
+ null, null, false);
mTargetWindow.mClient.dispatchDragEvent(evt);
if (myPid != mTargetWindow.mSession.mPid) {
evt.recycle();
@@ -679,7 +691,7 @@
}
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
- null, null);
+ null, null, false);
touchedWin.mClient.dispatchDragEvent(evt);
if (myPid != touchedWin.mSession.mPid) {
evt.recycle();
@@ -691,26 +703,43 @@
mTargetWindow = touchedWin;
}
- // Tell the drop target about the data, and then broadcast the drag-ended notification
- void notifyDropLw(float x, float y) {
+ // Tell the drop target about the data. Returns 'true' if we can immediately
+ // dispatch the global drag-ended message, 'false' if we need to wait for a
+ // result from the recipient.
+ boolean notifyDropLw(float x, float y) {
WindowState touchedWin = getTouchedWinAtPointLw(x, y);
- if (touchedWin != null) {
- if (DEBUG_DRAG) {
- Slog.d(TAG, "sending DROP to " + touchedWin);
- }
- final int myPid = Process.myPid();
- DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
- x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
- null, mData);
- try {
- touchedWin.mClient.dispatchDragEvent(evt);
- } catch (RemoteException e) {
- Slog.w(TAG, "can't send drop notification to win " + touchedWin);
- }
+ if (touchedWin == null) {
+ // "drop" outside a valid window -- no recipient to apply a
+ // timeout to, and we can send the drag-ended message immediately.
+ mDragResult = false;
+ return true;
+ }
+
+ if (DEBUG_DRAG) {
+ Slog.d(TAG, "sending DROP to " + touchedWin);
+ }
+ final int myPid = Process.myPid();
+ final IBinder token = touchedWin.mClient.asBinder();
+ DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
+ x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
+ null, mData, false);
+ try {
+ touchedWin.mClient.dispatchDragEvent(evt);
+
+ // 5 second timeout for this window to respond to the drop
+ mH.removeMessages(H.DRAG_END_TIMEOUT, token);
+ Message msg = mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
+ mH.sendMessageDelayed(msg, 5000);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "can't send drop notification to win " + touchedWin);
+ return true;
+ } finally {
if (myPid != touchedWin.mSession.mPid) {
evt.recycle();
}
}
+ mToken = token;
+ return false;
}
// Find the visible, touch-deliverable window under the given point
@@ -794,9 +823,8 @@
if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
+ newX + "," + newY);
synchronized (mWindowMap) {
- mDragState.notifyDropLw(newX, newY);
+ endDrag = mDragState.notifyDropLw(newX, newY);
}
- endDrag = true;
} break;
case MotionEvent.ACTION_CANCEL: {
@@ -808,17 +836,9 @@
if (endDrag) {
if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
// tell all the windows that the drag has ended
- mDragState.broadcastDragEnded();
-
- // stop intercepting input
- mDragState.unregister();
synchronized (mWindowMap) {
- mInputMonitor.updateInputWindowsLw();
+ mDragState.endDragLw();
}
-
- // free our resources and drop all the object references
- mDragState.reset();
- mDragState = null;
}
}
} catch (Exception e) {
@@ -5356,8 +5376,8 @@
// SVGA or larger screens at medium density are the point
// at which we consider it to be an extra large screen.
mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
- } else if (longSize >= 640 && shortSize >= 480) {
- // VGA or larger screens at medium density are the point
+ } else if (longSize >= 530 && shortSize >= 400) {
+ // SVGA or larger screens at high density are the point
// at which we consider it to be a large screen.
mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
} else {
@@ -6251,15 +6271,43 @@
return true; // success!
}
+ public void reportDropResult(IWindow window, boolean consumed) {
+ IBinder token = window.asBinder();
+ if (DEBUG_DRAG) {
+ Slog.d(TAG, "Drop result=" + consumed + " reported by " + token);
+ }
+
+ synchronized (mWindowMap) {
+ if (mDragState.mToken != token) {
+ Slog.w(TAG, "Invalid drop-result claim by " + window);
+ throw new IllegalStateException("reportDropResult() by non-recipient");
+ }
+
+ // The right window has responded, even if it's no longer around,
+ // so be sure to halt the timeout even if the later WindowState
+ // lookup fails.
+ mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
+
+ WindowState callingWin = windowForClientLocked(null, window, false);
+ if (callingWin == null) {
+ Slog.w(TAG, "Bad result-reporting window " + window);
+ return; // !!! TODO: throw here?
+ }
+
+ mDragState.mDragResult = consumed;
+ mDragState.endDragLw();
+ }
+ }
+
public void dragRecipientEntered(IWindow window) {
if (DEBUG_DRAG) {
- Slog.d(TAG, "Drag into new candidate view @ " + window);
+ Slog.d(TAG, "Drag into new candidate view @ " + window.asBinder());
}
}
public void dragRecipientExited(IWindow window) {
if (DEBUG_DRAG) {
- Slog.d(TAG, "Drag from old candidate view @ " + window);
+ Slog.d(TAG, "Drag from old candidate view @ " + window.asBinder());
}
}
@@ -8321,6 +8369,7 @@
public static final int SEND_NEW_CONFIGURATION = 18;
public static final int REPORT_WINDOWS_CHANGE = 19;
public static final int DRAG_START_TIMEOUT = 20;
+ public static final int DRAG_END_TIMEOUT = 21;
private Session mLastReportedHold;
@@ -8671,12 +8720,27 @@
synchronized (mWindowMap) {
// !!! TODO: ANR the app that has failed to start the drag in time
if (mDragState != null) {
+ mDragState.unregister();
+ mInputMonitor.updateInputWindowsLw();
mDragState.reset();
mDragState = null;
}
}
+ break;
}
+ case DRAG_END_TIMEOUT: {
+ IBinder win = (IBinder)msg.obj;
+ if (DEBUG_DRAG) {
+ Slog.w(TAG, "Timeout ending drag to win " + win);
+ }
+ synchronized (mWindowMap) {
+ // !!! TODO: ANR the drag-receiving app
+ mDragState.mDragResult = false;
+ mDragState.endDragLw();
+ }
+ break;
+ }
}
}
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 0623f5b..d469d67 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -136,7 +136,6 @@
static final long USB_DISCONNECT_DELAY = 1000;
public Tethering(Context context, Looper looper) {
- Log.d(TAG, "Tethering starting");
mContext = context;
mLooper = looper;
diff --git a/services/java/com/android/server/location/GpsXtraDownloader.java b/services/java/com/android/server/location/GpsXtraDownloader.java
index bc96980..813d255 100644
--- a/services/java/com/android/server/location/GpsXtraDownloader.java
+++ b/services/java/com/android/server/location/GpsXtraDownloader.java
@@ -44,6 +44,7 @@
public class GpsXtraDownloader {
private static final String TAG = "GpsXtraDownloader";
+ static final boolean DEBUG = false;
private Context mContext;
private String[] mXtraServers;
@@ -107,7 +108,7 @@
protected static byte[] doDownload(String url, boolean isProxySet,
String proxyHost, int proxyPort) {
- if (Config.LOGD) Log.d(TAG, "Downloading XTRA data from " + url);
+ if (DEBUG) Log.d(TAG, "Downloading XTRA data from " + url);
AndroidHttpClient client = null;
try {
@@ -130,7 +131,7 @@
HttpResponse response = client.execute(req);
StatusLine status = response.getStatusLine();
if (status.getStatusCode() != 200) { // HTTP 200 is success.
- if (Config.LOGD) Log.d(TAG, "HTTP error: " + status.getReasonPhrase());
+ if (DEBUG) Log.d(TAG, "HTTP error: " + status.getReasonPhrase());
return null;
}
@@ -159,7 +160,7 @@
}
return body;
} catch (Exception e) {
- if (Config.LOGD) Log.d(TAG, "error " + e);
+ if (DEBUG) Log.d(TAG, "error " + e);
} finally {
if (client != null) {
client.close();
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index 397a84a..d4513e9 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -164,7 +164,7 @@
jboolean value = false;
if (readFromFile(path, buf, SIZE) > 0) {
- if (buf[0] == '1') {
+ if (buf[0] != '0') {
value = true;
}
}
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index e4825d0..1c2a2c8 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -24,6 +24,10 @@
ifeq ($(TARGET_BOARD_PLATFORM), omap3)
LOCAL_CFLAGS += -DNO_RGBX_8888 -DHAS_PUSH_BUFFERS
endif
+ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
+ LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+endif
+
# need "-lrt" on Linux simulator to pick up clock_gettime
ifeq ($(TARGET_SIMULATOR),true)
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index bd348bf..8926c03 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -199,8 +199,18 @@
* Create our OpenGL ES context
*/
- context = eglCreateContext(display, config, NULL, NULL);
-
+
+ EGLint contextAttributes[] = {
+#ifdef EGL_IMG_context_priority
+#ifdef HAS_CONTEXT_PRIORITY
+#warning "using EGL_IMG_context_priority"
+ EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
+#endif
+#endif
+ EGL_NONE, EGL_NONE
+ };
+ context = eglCreateContext(display, config, NULL, contextAttributes);
+
mDisplay = display;
mConfig = config;
mSurface = surface;
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 3f0ec0a..ab7b601 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -1626,7 +1626,15 @@
}
-
+ private boolean hasMoreThanOneRingingCall() {
+ int count = 0;
+ for (Call call : mRingingCalls) {
+ if (call.getState().isRinging()) {
+ if (++count > 1) return true;
+ }
+ }
+ return false;
+ }
private Handler mHandler = new Handler() {
@@ -1644,7 +1652,17 @@
break;
case EVENT_NEW_RINGING_CONNECTION:
if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");
- mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
+ if (getActiveFgCallState().isDialing() || hasMoreThanOneRingingCall()) {
+ Connection c = (Connection) ((AsyncResult) msg.obj).result;
+ try {
+ Log.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
+ c.getCall().hangup();
+ } catch (CallStateException e) {
+ Log.w(LOG_TAG, "new ringing connection", e);
+ }
+ } else {
+ mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
+ }
break;
case EVENT_UNKNOWN_CONNECTION:
if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)");
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index db16dec..82fcb6a 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -267,6 +267,7 @@
Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
CallerInfo info = getCallerInfo(context, contactUri);
+ info = doSecondaryLookupIfNecessary(context, number, info);
// if no query results were returned with a viable number,
// fill in the original number value we used to query with.
@@ -278,6 +279,30 @@
}
/**
+ * Performs another lookup if previous lookup fails and it's a SIP call
+ * and the peer's username is all numeric. Look up the username as it
+ * could be a PSTN number in the contact database.
+ *
+ * @param context the query context
+ * @param number the original phone number, could be a SIP URI
+ * @param previousResult the result of previous lookup
+ * @return previousResult if it's not the case
+ */
+ static CallerInfo doSecondaryLookupIfNecessary(Context context,
+ String number, CallerInfo previousResult) {
+ if (!previousResult.contactExists
+ && PhoneNumberUtils.isUriNumber(number)) {
+ String username = number.substring(0, number.indexOf('@'));
+ if (PhoneNumberUtils.isGlobalPhoneNumber(username)) {
+ previousResult = getCallerInfo(context,
+ Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
+ Uri.encode(username)));
+ }
+ }
+ return previousResult;
+ }
+
+ /**
* getCallerId: a convenience method to get the caller id for a given
* number.
*
@@ -409,6 +434,7 @@
.append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent)
.append("\nemergency: " + mIsEmergency)
.append("\nvoicemail " + mIsVoiceMail)
+ .append("\ncontactExists " + contactExists)
.toString();
}
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 8471efa..c47e076 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -38,7 +38,7 @@
*/
public class CallerInfoAsyncQuery {
- private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
+ private static final boolean DBG = false;
private static final String LOG_TAG = "CallerInfoAsyncQuery";
private static final int EVENT_NEW_QUERY = 1;
@@ -129,13 +129,13 @@
// However, if there is any code that this Handler calls (such as in
// super.handleMessage) that DOES place unexpected messages on the
// queue, then we need pass these messages on.
- if (DBG) log("Unexpected command (CookieWrapper is null): " + msg.what +
+ if (DBG) Log.d(LOG_TAG, "Unexpected command (CookieWrapper is null): " + msg.what +
" ignored by CallerInfoWorkerHandler, passing onto parent.");
super.handleMessage(msg);
} else {
- if (DBG) log("Processing event: " + cw.event + " token (arg1): " + msg.arg1 +
+ if (DBG) Log.d(LOG_TAG, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 +
" command: " + msg.what + " query URI: " + sanitizeUriToString(args.uri));
switch (cw.event) {
@@ -191,7 +191,7 @@
*/
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- if (DBG) log("##### onQueryComplete() ##### query complete for token: " + token);
+ if (DBG) Log.d(LOG_TAG, "##### onQueryComplete() ##### query complete for token: " + token);
//get the cookie and notify the listener.
CookieWrapper cw = (CookieWrapper) cookie;
@@ -200,7 +200,7 @@
// from within this code.
// However, if there is any code that calls this method, we should
// check the parameters to make sure they're viable.
- if (DBG) log("Cookie is null, ignoring onQueryComplete() request.");
+ if (DBG) Log.d(LOG_TAG, "Cookie is null, ignoring onQueryComplete() request.");
return;
}
@@ -229,7 +229,15 @@
mCallerInfo = new CallerInfo().markAsVoiceMail();
} else {
mCallerInfo = CallerInfo.getCallerInfo(mQueryContext, mQueryUri, cursor);
- if (DBG) log("==> Got mCallerInfo: " + mCallerInfo);
+ if (DBG) Log.d(LOG_TAG, "==> Got mCallerInfo: " + mCallerInfo);
+
+ CallerInfo newCallerInfo = CallerInfo.doSecondaryLookupIfNecessary(
+ mQueryContext, cw.number, mCallerInfo);
+ if (newCallerInfo != mCallerInfo) {
+ mCallerInfo = newCallerInfo;
+ if (DBG) Log.d(LOG_TAG, "#####async contact look up with numeric username"
+ + mCallerInfo);
+ }
// Use the number entered by the user for display.
if (!TextUtils.isEmpty(cw.number)) {
@@ -241,7 +249,7 @@
}
}
- if (DBG) log("constructing CallerInfo object for token: " + token);
+ if (DBG) Log.d(LOG_TAG, "constructing CallerInfo object for token: " + token);
//notify that we can clean up the queue after this.
CookieWrapper endMarker = new CookieWrapper();
@@ -251,7 +259,7 @@
//notify the listener that the query is complete.
if (cw.listener != null) {
- if (DBG) log("notifying listener: " + cw.listener.getClass().toString() +
+ if (DBG) Log.d(LOG_TAG, "notifying listener: " + cw.listener.getClass().toString() +
" for token: " + token + mCallerInfo);
cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo);
}
@@ -274,7 +282,7 @@
CallerInfoAsyncQuery c = new CallerInfoAsyncQuery();
c.allocate(context, contactRef);
- if (DBG) log("starting query for URI: " + contactRef + " handler: " + c.toString());
+ if (DBG) Log.d(LOG_TAG, "starting query for URI: " + contactRef + " handler: " + c.toString());
//create cookieWrapper, start query
CookieWrapper cw = new CookieWrapper();
@@ -301,9 +309,9 @@
public static CallerInfoAsyncQuery startQuery(int token, Context context, String number,
OnQueryCompleteListener listener, Object cookie) {
if (DBG) {
- log("##### CallerInfoAsyncQuery startQuery()... #####");
- log("- number: " + /*number*/ "xxxxxxx");
- log("- cookie: " + cookie);
+ Log.d(LOG_TAG, "##### CallerInfoAsyncQuery startQuery()... #####");
+ Log.d(LOG_TAG, "- number: " + /*number*/ "xxxxxxx");
+ Log.d(LOG_TAG, "- cookie: " + cookie);
}
// Construct the URI object and query params, and start the query.
@@ -314,7 +322,7 @@
if (PhoneNumberUtils.isUriNumber(number)) {
// "number" is really a SIP address.
- if (DBG) log(" - Treating number as a SIP address: " + /*number*/ "xxxxxxx");
+ if (DBG) Log.d(LOG_TAG, " - Treating number as a SIP address: " + /*number*/ "xxxxxxx");
// We look up SIP addresses directly in the Data table:
contactRef = Data.CONTENT_URI;
@@ -346,11 +354,11 @@
}
if (DBG) {
- log("==> contactRef: " + sanitizeUriToString(contactRef));
- log("==> selection: " + selection);
+ Log.d(LOG_TAG, "==> contactRef: " + sanitizeUriToString(contactRef));
+ Log.d(LOG_TAG, "==> selection: " + selection);
if (selectionArgs != null) {
for (int i = 0; i < selectionArgs.length; i++) {
- log("==> selectionArgs[" + i + "]: " + selectionArgs[i]);
+ Log.d(LOG_TAG, "==> selectionArgs[" + i + "]: " + selectionArgs[i]);
}
}
}
@@ -388,7 +396,7 @@
*/
public void addQueryListener(int token, OnQueryCompleteListener listener, Object cookie) {
- if (DBG) log("adding listener to query: " + sanitizeUriToString(mHandler.mQueryUri) +
+ if (DBG) Log.d(LOG_TAG, "adding listener to query: " + sanitizeUriToString(mHandler.mQueryUri) +
" handler: " + mHandler.toString());
//create cookieWrapper, add query request to end of queue.
@@ -436,11 +444,4 @@
return "";
}
}
-
- /**
- * static logging method
- */
- private static void log(String msg) {
- Log.d(LOG_TAG, msg);
- }
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
index 209fe06..c83f696 100644
--- a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java
@@ -50,7 +50,7 @@
* calculating deltas.
*/
private long connectTimeReal;
- private long duration;
+ private long duration = -1L;
private long holdingStartTime; // The time when the Connection last transitioned
// into HOLDING
@@ -75,7 +75,7 @@
}
break;
case DISCONNECTED:
- duration = SystemClock.elapsedRealtime() - connectTimeReal;
+ duration = getDurationMillis();
disconnectTime = System.currentTimeMillis();
break;
case HOLDING:
@@ -103,7 +103,7 @@
public long getDurationMillis() {
if (connectTimeReal == 0) {
return 0;
- } else if (duration == 0) {
+ } else if (duration < 0) {
return SystemClock.elapsedRealtime() - connectTimeReal;
} else {
return duration;
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 09d3c8e..ef31ddd 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -28,6 +28,7 @@
import android.os.Message;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.telephony.Call;
@@ -483,7 +484,12 @@
void merge(SipCall that) throws CallStateException {
AudioGroup audioGroup = getAudioGroup();
- for (Connection c : that.connections) {
+
+ // copy to an array to avoid concurrent modification as connections
+ // in that.connections will be removed in add(SipConnection).
+ Connection[] cc = that.connections.toArray(
+ new Connection[that.connections.size()]);
+ for (Connection c : cc) {
SipConnection conn = (SipConnection) c;
add(conn);
if (conn.getState() == Call.State.HOLDING) {
@@ -676,6 +682,18 @@
this(owner, callee, getUriString(callee));
}
+ @Override
+ public String getCnapName() {
+ String displayName = mPeer.getDisplayName();
+ return TextUtils.isEmpty(displayName) ? null
+ : displayName;
+ }
+
+ @Override
+ public int getNumberPresentation() {
+ return Connection.PRESENTATION_ALLOWED;
+ }
+
void initIncomingCall(SipAudioCall sipAudioCall, Call.State newState) {
setState(newState);
mSipAudioCall = sipAudioCall;
@@ -704,7 +722,6 @@
setState(Call.State.DIALING);
mSipAudioCall = mSipManager.makeAudioCall(mProfile, mPeer, null,
TIMEOUT_MAKE_CALL);
- mSipAudioCall.setRingbackToneEnabled(false);
mSipAudioCall.setListener(mAdapter);
}
@@ -789,7 +806,9 @@
@Override
public void separate() throws CallStateException {
synchronized (SipPhone.class) {
- SipCall call = (SipCall) SipPhone.this.getBackgroundCall();
+ SipCall call = (getPhone() == SipPhone.this)
+ ? (SipCall) SipPhone.this.getBackgroundCall()
+ : (SipCall) SipPhone.this.getForegroundCall();
if (call.getState() != Call.State.IDLE) {
throw new CallStateException(
"cannot put conn back to a call in non-idle state: "
@@ -799,10 +818,20 @@
+ mPeer.getUriString() + " from " + mOwner + " back to "
+ call);
+ // separate the AudioGroup and connection from the original call
+ Phone originalPhone = getPhone();
AudioGroup audioGroup = call.getAudioGroup(); // may be null
call.add(this);
mSipAudioCall.setAudioGroup(audioGroup);
- call.hold();
+
+ // put the original call to bg; and the separated call becomes
+ // fg if it was in bg
+ originalPhone.switchHoldingAndActive();
+
+ // start audio and notify the phone app of the state change
+ call = (SipCall) SipPhone.this.getForegroundCall();
+ mSipAudioCall.startAudio();
+ call.onConnectionStateChanged(this);
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 0553f5e..eb0eba2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -1093,6 +1093,11 @@
}
@SuppressWarnings("unused")
+ public void reportDropResult(IWindow window, boolean consumed) throws RemoteException {
+ // pass for now
+ }
+
+ @SuppressWarnings("unused")
public void dragRecipientEntered(IWindow window) throws RemoteException {
// pass for now
}
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index d859c4c..0179748 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -18,10 +18,6 @@
import android.content.Context;
import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.media.ToneGenerator;
-import android.net.Uri;
import android.net.rtp.AudioCodec;
import android.net.rtp.AudioGroup;
import android.net.rtp.AudioStream;
@@ -30,8 +26,6 @@
import android.net.wifi.WifiManager;
import android.os.Message;
import android.os.RemoteException;
-import android.os.Vibrator;
-import android.provider.Settings;
import android.util.Log;
import java.io.IOException;
@@ -47,6 +41,16 @@
* facilitates instantiating a {@code SipAudioCall} object for making/receiving
* calls. See {@link SipManager#makeAudioCall} and
* {@link SipManager#takeAudioCall}.
+ *
+ * <p>Requires permissions to use this class:
+ * {@link android.Manifest.permission#INTERNET} and
+ * {@link android.Manifest.permission#USE_SIP}.
+ * <br/>Requires permissions to {@link #startAudio}:
+ * {@link android.Manifest.permission#RECORD_AUDIO},
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
+ * {@link android.Manifest.permission#WAKE_LOCK}.
+ * <br/>Requires permissions to {@link #setSpeakerMode}:
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
*/
public class SipAudioCall {
private static final String TAG = SipAudioCall.class.getSimpleName();
@@ -175,11 +179,6 @@
private boolean mMuted = false;
private boolean mHold = false;
- private boolean mRingbackToneEnabled = true;
- private boolean mRingtoneEnabled = true;
- private Ringtone mRingtone;
- private ToneGenerator mRingbackTone;
-
private SipProfile mPendingCallRequest;
private WifiManager mWm;
private WifiManager.WifiLock mWifiHighPerfLock;
@@ -285,8 +284,6 @@
private synchronized void close(boolean closeRtp) {
if (closeRtp) stopCall(RELEASE_SOCKET);
- stopRingbackTone();
- stopRinging();
mInCall = false;
mHold = false;
@@ -366,7 +363,6 @@
@Override
public void onRingingBack(SipSession session) {
Log.d(TAG, "sip call ringing back: " + session);
- if (!mInCall) startRingbackTone();
Listener listener = mListener;
if (listener != null) {
try {
@@ -403,8 +399,6 @@
@Override
public void onCallEstablished(SipSession session,
String sessionDescription) {
- stopRingbackTone();
- stopRinging();
mPeerSd = sessionDescription;
Log.v(TAG, "onCallEstablished()" + mPeerSd);
@@ -533,10 +527,6 @@
Log.v(TAG, "attachCall()" + mPeerSd);
try {
session.setListener(createListener());
-
- if (getState() == SipSession.State.INCOMING_CALL) {
- startRinging();
- }
} catch (Throwable e) {
Log.e(TAG, "attachCall()", e);
throwSipException(e);
@@ -580,7 +570,6 @@
*/
public void endCall() throws SipException {
synchronized (this) {
- stopRinging();
stopCall(RELEASE_SOCKET);
mInCall = false;
@@ -625,7 +614,6 @@
*/
public void answerCall(int timeout) throws SipException {
synchronized (this) {
- stopRinging();
try {
mAudioStream = new AudioStream(InetAddress.getByName(
getLocalIp()));
@@ -798,7 +786,11 @@
}
}
- /** Puts the device to speaker mode. */
+ /**
+ * Puts the device to speaker mode.
+ * <p>Requires permission:
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
+ */
public void setSpeakerMode(boolean speakerMode) {
synchronized (this) {
((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
@@ -898,6 +890,10 @@
/**
* Starts the audio for the established call. This method should be called
* after {@link Listener#onCallEstablished} is called.
+ * <p>Requires permission:
+ * {@link android.Manifest.permission#RECORD_AUDIO},
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
+ * {@link android.Manifest.permission#WAKE_LOCK}.
*/
public void startAudio() {
try {
@@ -1026,69 +1022,6 @@
return mSipSession.getLocalIp();
}
-
- /**
- * Enables/disables the ring-back tone.
- *
- * @param enabled true to enable; false to disable
- */
- public void setRingbackToneEnabled(boolean enabled) {
- synchronized (this) {
- mRingbackToneEnabled = enabled;
- }
- }
-
- /**
- * Enables/disables the ring tone.
- *
- * @param enabled true to enable; false to disable
- */
- public void setRingtoneEnabled(boolean enabled) {
- synchronized (this) {
- mRingtoneEnabled = enabled;
- }
- }
-
- private void startRingbackTone() {
- if (!mRingbackToneEnabled) return;
- if (mRingbackTone == null) {
- // The volume relative to other sounds in the stream
- int toneVolume = 80;
- mRingbackTone = new ToneGenerator(
- AudioManager.STREAM_VOICE_CALL, toneVolume);
- }
- mRingbackTone.startTone(ToneGenerator.TONE_CDMA_LOW_PBX_L);
- }
-
- private void stopRingbackTone() {
- if (mRingbackTone != null) {
- mRingbackTone.stopTone();
- mRingbackTone.release();
- mRingbackTone = null;
- }
- }
-
- private void startRinging() {
- if (!mRingtoneEnabled) return;
- ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
- .vibrate(new long[] {0, 1000, 1000}, 1);
- AudioManager am = (AudioManager)
- mContext.getSystemService(Context.AUDIO_SERVICE);
- if (am.getStreamVolume(AudioManager.STREAM_RING) > 0) {
- String ringtoneUri =
- Settings.System.DEFAULT_RINGTONE_URI.toString();
- mRingtone = RingtoneManager.getRingtone(mContext,
- Uri.parse(ringtoneUri));
- mRingtone.play();
- }
- }
-
- private void stopRinging() {
- ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
- .cancel();
- if (mRingtone != null) mRingtone.stop();
- }
-
private void throwSipException(Throwable throwable) throws SipException {
if (throwable instanceof SipException) {
throw (SipException) throwable;
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index 2f03e34..38d2b0c 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -50,6 +50,9 @@
* </ul>
* {@code SipManager} can only be instantiated if SIP API is supported by the
* device. (See {@link #isApiSupported}).
+ * <p>Requires permissions to use this class:
+ * {@link android.Manifest.permission#INTERNET} and
+ * {@link android.Manifest.permission#USE_SIP}.
*/
public class SipManager {
/**
@@ -351,17 +354,6 @@
}
/**
- * The method calls {@code takeAudioCall(incomingCallIntent,
- * listener, true}.
- *
- * @see #takeAudioCall(Intent, SipAudioCall.Listener, boolean)
- */
- public SipAudioCall takeAudioCall(Intent incomingCallIntent,
- SipAudioCall.Listener listener) throws SipException {
- return takeAudioCall(incomingCallIntent, listener, true);
- }
-
- /**
* Creates a {@link SipAudioCall} to take an incoming call. Before the call
* is returned, the listener will receive a
* {@link SipAudioCall.Listener#onRinging}
@@ -374,8 +366,7 @@
* @throws SipException if calling the SIP service results in an error
*/
public SipAudioCall takeAudioCall(Intent incomingCallIntent,
- SipAudioCall.Listener listener, boolean ringtoneEnabled)
- throws SipException {
+ SipAudioCall.Listener listener) throws SipException {
if (incomingCallIntent == null) return null;
String callId = getCallId(incomingCallIntent);
@@ -394,7 +385,6 @@
if (session == null) return null;
SipAudioCall call = new SipAudioCall(
mContext, session.getLocalProfile());
- call.setRingtoneEnabled(ringtoneEnabled);
call.attachCall(new SipSession(session), offerSd);
call.setListener(listener);
return call;
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 2514262..13e6f14 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -365,6 +365,10 @@
Response response = mMessageFactory.createResponse(
Response.BUSY_HERE, request);
+ if (inviteTransaction == null) {
+ inviteTransaction = getServerTransaction(event);
+ }
+
if (inviteTransaction.getState() != TransactionState.COMPLETED) {
if (DEBUG) Log.d(TAG, "send BUSY HERE: " + response);
inviteTransaction.sendResponse(response);
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 1df08c0..84e0803 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -68,7 +68,7 @@
public final class SipService extends ISipService.Stub {
static final String TAG = "SipService";
static final boolean DEBUGV = false;
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final boolean DEBUG_TIMER = DEBUG && false;
private static final int EXPIRY_TIME = 3600;
private static final int SHORT_EXPIRY_TIME = 10;
@@ -79,6 +79,7 @@
private String mNetworkType;
private boolean mConnected;
private WakeupTimer mTimer;
+ private WifiScanProcess mWifiScanProcess;
private WifiManager.WifiLock mWifiLock;
private boolean mWifiOnly;
@@ -104,7 +105,7 @@
if (SipManager.isApiSupported(context)) {
ServiceManager.addService("sip", new SipService(context));
context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP));
- Log.i(TAG, "SIP service started");
+ if (DEBUG) Log.i(TAG, "SIP service started");
}
}
@@ -222,7 +223,7 @@
SipSessionGroupExt group = mSipGroups.get(localProfileUri);
if (group == null) return;
if (!isCallerCreatorOrRadio(group)) {
- Log.d(TAG, "only creator or radio can close this profile");
+ Log.w(TAG, "only creator or radio can close this profile");
return;
}
@@ -244,7 +245,7 @@
if (isCallerCreatorOrRadio(group)) {
return group.isOpened();
} else {
- Log.i(TAG, "only creator or radio can query on the profile");
+ Log.w(TAG, "only creator or radio can query on the profile");
return false;
}
}
@@ -257,7 +258,7 @@
if (isCallerCreatorOrRadio(group)) {
return group.isRegistered();
} else {
- Log.i(TAG, "only creator or radio can query on the profile");
+ Log.w(TAG, "only creator or radio can query on the profile");
return false;
}
}
@@ -271,7 +272,7 @@
if (isCallerCreator(group)) {
group.setListener(listener);
} else {
- Log.i(TAG, "only creator can set listener on the profile");
+ Log.w(TAG, "only creator can set listener on the profile");
}
}
@@ -285,7 +286,7 @@
SipSessionGroupExt group = createGroup(localProfile);
return group.createSession(listener);
} catch (SipException e) {
- Log.w(TAG, "createSession()", e);
+ if (DEBUG) Log.d(TAG, "createSession()", e);
return null;
}
}
@@ -303,7 +304,7 @@
s.connect(InetAddress.getByName("192.168.1.1"), 80);
return s.getLocalAddress().getHostAddress();
} catch (IOException e) {
- Log.w(TAG, "determineLocalIp()", e);
+ if (DEBUG) Log.d(TAG, "determineLocalIp()", e);
// dont do anything; there should be a connectivity change going
return null;
}
@@ -371,6 +372,7 @@
mContext.getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG);
mWifiLock.acquire();
+ if (!mConnected) startWifiScanner();
}
}
@@ -379,6 +381,20 @@
if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ release wifi lock");
mWifiLock.release();
mWifiLock = null;
+ stopWifiScanner();
+ }
+ }
+
+ private synchronized void startWifiScanner() {
+ if (mWifiScanProcess == null) {
+ mWifiScanProcess = new WifiScanProcess();
+ }
+ mWifiScanProcess.start();
+ }
+
+ private synchronized void stopWifiScanner() {
+ if (mWifiScanProcess != null) {
+ mWifiScanProcess.stop();
}
}
@@ -413,8 +429,10 @@
for (SipSessionGroupExt group : mSipGroups.values()) {
group.onConnectivityChanged(true);
}
+ if (isWifi && (mWifiLock != null)) stopWifiScanner();
} else {
mMyWakeLock.reset(); // in case there's a leak
+ if (isWifi && (mWifiLock != null)) startWifiScanner();
}
} catch (SipException e) {
Log.e(TAG, "onConnectivityChanged()", e);
@@ -430,6 +448,21 @@
}
}
+ private synchronized boolean callingSelf(SipSessionGroupExt ringingGroup,
+ SipSessionGroup.SipSessionImpl ringingSession) {
+ String callId = ringingSession.getCallId();
+ for (SipSessionGroupExt group : mSipGroups.values()) {
+ if ((group != ringingGroup) && group.containsSession(callId)) {
+ if (DEBUG) Log.d(TAG, "call self: "
+ + ringingSession.getLocalProfile().getUriString()
+ + " -> " + group.getLocalProfile().getUriString());
+ return true;
+ }
+ }
+ return false;
+ }
+
+
private class SipSessionGroupExt extends SipSessionAdapter {
private SipSessionGroup mSipGroup;
private PendingIntent mIncomingCallPendingIntent;
@@ -452,6 +485,10 @@
return mSipGroup.getLocalProfile();
}
+ public boolean containsSession(String callId) {
+ return mSipGroup.containsSession(callId);
+ }
+
// network connectivity is tricky because network can be disconnected
// at any instant so need to deal with exceptions carefully even when
// you think you are connected
@@ -467,7 +504,7 @@
return createSipSessionGroup(null, localProfile, password);
} else {
// recursive
- Log.wtf(TAG, "impossible!");
+ Log.wtf(TAG, "impossible! recursive!");
throw new RuntimeException("createSipSessionGroup");
}
}
@@ -551,7 +588,7 @@
(SipSessionGroup.SipSessionImpl) s;
synchronized (SipService.this) {
try {
- if (!isRegistered()) {
+ if (!isRegistered() || callingSelf(this, session)) {
session.endCall();
return;
}
@@ -592,6 +629,36 @@
}
}
+ private class WifiScanProcess implements Runnable {
+ private static final String TAG = "\\WIFI_SCAN/";
+ private static final int INTERVAL = 60;
+ private boolean mRunning = false;
+
+ private WifiManager mWifiManager;
+
+ public void start() {
+ if (mRunning) return;
+ mRunning = true;
+ mTimer.set(INTERVAL * 1000, this);
+ }
+
+ WifiScanProcess() {
+ mWifiManager = (WifiManager)
+ mContext.getSystemService(Context.WIFI_SERVICE);
+ }
+
+ public void run() {
+ // scan and associate now
+ if (DEBUGV) Log.v(TAG, "just wake up here for wifi scanning...");
+ mWifiManager.startScanActive();
+ }
+
+ public void stop() {
+ mRunning = false;
+ mTimer.cancel(this);
+ }
+ }
+
// KeepAliveProcess is controlled by AutoRegistrationProcess.
// All methods will be invoked in sync with SipService.this.
private class KeepAliveProcess implements Runnable {
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index bb246a6..50ce7dc 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -231,6 +231,10 @@
}
}
+ synchronized boolean containsSession(String callId) {
+ return mSessionMap.containsKey(callId);
+ }
+
private synchronized SipSessionImpl getSipSession(EventObject event) {
String key = SipHelper.getCallId(event);
SipSessionImpl session = mSessionMap.get(key);
@@ -582,6 +586,7 @@
}
private void processCommand(EventObject command) throws SipException {
+ if (isLoggable(command)) Log.d(TAG, "process cmd: " + command);
if (!process(command)) {
onError(SipErrorCode.IN_PROGRESS,
"cannot initiate a new transaction to execute: "
@@ -1050,6 +1055,13 @@
mSipHelper.sendCancel(mClientTransaction);
startSessionTimer(CANCEL_CALL_TIMER);
return true;
+ } else if (isRequestEvent(Request.INVITE, evt)) {
+ // Call self? Send BUSY HERE so server may redirect the call to
+ // voice mailbox.
+ RequestEvent event = (RequestEvent) evt;
+ mSipHelper.sendInviteBusyHere(event,
+ event.getServerTransaction());
+ return true;
}
return false;
}
@@ -1351,6 +1363,10 @@
return DEBUG;
}
+ private static boolean isLoggable(EventObject evt) {
+ return isLoggable(null, evt);
+ }
+
private static boolean isLoggable(SipSessionImpl s, EventObject evt) {
if (!isLoggable(s)) return false;
if (evt == null) return false;
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 9da560a..0c8a725 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -768,7 +768,7 @@
LOGD("latency: output %d, input %d", track.latency(), record.latency());
// Initialize echo canceler.
- EchoSuppressor echo(sampleRate, sampleCount, sampleCount * 2 +
+ EchoSuppressor echo(sampleCount,
(track.latency() + record.latency()) * sampleRate / 1000);
// Give device socket a reasonable buffer size.
diff --git a/voip/jni/rtp/EchoSuppressor.cpp b/voip/jni/rtp/EchoSuppressor.cpp
index fbeb315..4cff588 100644
--- a/voip/jni/rtp/EchoSuppressor.cpp
+++ b/voip/jni/rtp/EchoSuppressor.cpp
@@ -25,146 +25,163 @@
#include "EchoSuppressor.h"
-EchoSuppressor::EchoSuppressor(int sampleRate, int sampleCount, int tailLength)
+// It is very difficult to do echo cancellation at this level due to the lack of
+// the timing information of the samples being played and recorded. Therefore,
+// for the first release only echo suppression is implemented.
+
+// The algorithm is derived from the "previous works" summarized in
+// A new class of doubletalk detectors based on cross-correlation,
+// J Benesty, DR Morgan, JH Cho, IEEE Trans. on Speech and Audio Processing.
+// The method proposed in that paper is not used because of its high complexity.
+
+// It is well known that cross-correlation can be computed using convolution,
+// but unfortunately not every mobile processor has a (fast enough) FPU. Thus
+// we use integer arithmetic as much as possible and do lots of bookkeeping.
+// Again, parameters and thresholds are chosen by experiments.
+
+EchoSuppressor::EchoSuppressor(int sampleCount, int tailLength)
{
- int scale = 1;
- while (tailLength > 200 * scale) {
- scale <<= 1;
- }
- if (scale > sampleCount) {
- scale = sampleCount;
+ tailLength += sampleCount * 4;
+
+ int shift = 0;
+ while ((sampleCount >> shift) > 1 && (tailLength >> shift) > 256) {
+ ++shift;
}
- mScale = scale;
+ mShift = shift + 4;
+ mScale = 1 << shift;
mSampleCount = sampleCount;
- mWindowSize = sampleCount / scale;
- mTailLength = (tailLength + scale - 1) / scale;
- mRecordLength = (sampleRate + sampleCount - 1) / sampleCount;
+ mWindowSize = sampleCount >> shift;
+ mTailLength = tailLength >> shift;
+ mRecordLength = tailLength * 2 / sampleCount;
mRecordOffset = 0;
- mXs = new float[mTailLength + mWindowSize];
- memset(mXs, 0, sizeof(float) * (mTailLength + mWindowSize));
- mXYs = new float[mTailLength];
- memset(mXYs, 0, sizeof(float) * mTailLength);
- mXXs = new float[mTailLength];
- memset(mXYs, 0, sizeof(float) * mTailLength);
- mYY = 0;
+ mXs = new uint16_t[mTailLength + mWindowSize];
+ memset(mXs, 0, sizeof(*mXs) * (mTailLength + mWindowSize));
+ mXSums = new uint32_t[mTailLength];
+ memset(mXSums, 0, sizeof(*mXSums) * mTailLength);
+ mX2Sums = new uint32_t[mTailLength];
+ memset(mX2Sums, 0, sizeof(*mX2Sums) * mTailLength);
+ mXRecords = new uint16_t[mRecordLength * mWindowSize];
+ memset(mXRecords, 0, sizeof(*mXRecords) * mRecordLength * mWindowSize);
- mXYRecords = new float[mRecordLength * mTailLength];
- memset(mXYRecords, 0, sizeof(float) * mRecordLength * mTailLength);
- mXXRecords = new float[mRecordLength * mWindowSize];
- memset(mXXRecords, 0, sizeof(float) * mRecordLength * mWindowSize);
- mYYRecords = new float[mRecordLength];
- memset(mYYRecords, 0, sizeof(float) * mRecordLength);
+ mYSum = 0;
+ mY2Sum = 0;
+ mYRecords = new uint32_t[mRecordLength];
+ memset(mYRecords, 0, sizeof(*mYRecords) * mRecordLength);
+ mY2Records = new uint32_t[mRecordLength];
+ memset(mY2Records, 0, sizeof(*mY2Records) * mRecordLength);
+
+ mXYSums = new uint32_t[mTailLength];
+ memset(mXYSums, 0, sizeof(*mXYSums) * mTailLength);
+ mXYRecords = new uint32_t[mRecordLength * mTailLength];
+ memset(mXYRecords, 0, sizeof(*mXYRecords) * mRecordLength * mTailLength);
mLastX = 0;
mLastY = 0;
+ mWeight = 1.0f / (mRecordLength * mWindowSize);
}
EchoSuppressor::~EchoSuppressor()
{
delete [] mXs;
- delete [] mXYs;
- delete [] mXXs;
+ delete [] mXSums;
+ delete [] mX2Sums;
+ delete [] mXRecords;
+ delete [] mYRecords;
+ delete [] mY2Records;
+ delete [] mXYSums;
delete [] mXYRecords;
- delete [] mXXRecords;
- delete [] mYYRecords;
}
void EchoSuppressor::run(int16_t *playbacked, int16_t *recorded)
{
- float *records;
-
// Update Xs.
- for (int i = 0; i < mTailLength; ++i) {
- mXs[i] = mXs[mWindowSize + i];
+ for (int i = mTailLength - 1; i >= 0; --i) {
+ mXs[i + mWindowSize] = mXs[i];
}
- for (int i = 0, j = 0; i < mWindowSize; ++i, j += mScale) {
- float sum = 0;
+ for (int i = mWindowSize - 1, j = 0; i >= 0; --i, j += mScale) {
+ uint32_t sum = 0;
for (int k = 0; k < mScale; ++k) {
- float x = playbacked[j + k] >> 8;
+ int32_t x = playbacked[j + k] << 15;
mLastX += x;
- sum += (mLastX >= 0) ? mLastX : -mLastX;
- mLastX = 0.005f * mLastX - x;
+ sum += ((mLastX >= 0) ? mLastX : -mLastX) >> 15;
+ mLastX -= (mLastX >> 10) + x;
}
- mXs[mTailLength - 1 + i] = sum;
+ mXs[i] = sum >> mShift;
}
- // Update XXs and XXRecords.
- for (int i = 0; i < mTailLength - mWindowSize; ++i) {
- mXXs[i] = mXXs[mWindowSize + i];
+ // Update XSums, X2Sums, and XRecords.
+ for (int i = mTailLength - mWindowSize - 1; i >= 0; --i) {
+ mXSums[i + mWindowSize] = mXSums[i];
+ mX2Sums[i + mWindowSize] = mX2Sums[i];
}
- records = &mXXRecords[mRecordOffset * mWindowSize];
- for (int i = 0, j = mTailLength - mWindowSize; i < mWindowSize; ++i, ++j) {
- float xx = mXs[mTailLength - 1 + i] * mXs[mTailLength - 1 + i];
- mXXs[j] = mXXs[j - 1] + xx - records[i];
- records[i] = xx;
- if (mXXs[j] < 0) {
- mXXs[j] = 0;
- }
+ uint16_t *xRecords = &mXRecords[mRecordOffset * mWindowSize];
+ for (int i = mWindowSize - 1; i >= 0; --i) {
+ uint16_t x = mXs[i];
+ mXSums[i] = mXSums[i + 1] + x - xRecords[i];
+ mX2Sums[i] = mX2Sums[i + 1] + x * x - xRecords[i] * xRecords[i];
+ xRecords[i] = x;
}
// Compute Ys.
- float ys[mWindowSize];
- for (int i = 0, j = 0; i < mWindowSize; ++i, j += mScale) {
- float sum = 0;
+ uint16_t ys[mWindowSize];
+ for (int i = mWindowSize - 1, j = 0; i >= 0; --i, j += mScale) {
+ uint32_t sum = 0;
for (int k = 0; k < mScale; ++k) {
- float y = recorded[j + k] >> 8;
+ int32_t y = recorded[j + k] << 15;
mLastY += y;
- sum += (mLastY >= 0) ? mLastY : -mLastY;
- mLastY = 0.005f * mLastY - y;
+ sum += ((mLastY >= 0) ? mLastY : -mLastY) >> 15;
+ mLastY -= (mLastY >> 10) + y;
}
- ys[i] = sum;
+ ys[i] = sum >> mShift;
}
- // Update YY and YYRecords.
- float yy = 0;
- for (int i = 0; i < mWindowSize; ++i) {
- yy += ys[i] * ys[i];
+ // Update YSum, Y2Sum, YRecords, and Y2Records.
+ uint32_t ySum = 0;
+ uint32_t y2Sum = 0;
+ for (int i = mWindowSize - 1; i >= 0; --i) {
+ ySum += ys[i];
+ y2Sum += ys[i] * ys[i];
}
- mYY += yy - mYYRecords[mRecordOffset];
- mYYRecords[mRecordOffset] = yy;
- if (mYY < 0) {
- mYY = 0;
+ mYSum += ySum - mYRecords[mRecordOffset];
+ mY2Sum += y2Sum - mY2Records[mRecordOffset];
+ mYRecords[mRecordOffset] = ySum;
+ mY2Records[mRecordOffset] = y2Sum;
+
+ // Update XYSums and XYRecords.
+ uint32_t *xyRecords = &mXYRecords[mRecordOffset * mTailLength];
+ for (int i = mTailLength - 1; i >= 0; --i) {
+ uint32_t xySum = 0;
+ for (int j = mWindowSize - 1; j >= 0; --j) {
+ xySum += mXs[i + j] * ys[j];
+ }
+ mXYSums[i] += xySum - xyRecords[i];
+ xyRecords[i] = xySum;
}
- // Update XYs and XYRecords.
- records = &mXYRecords[mRecordOffset * mTailLength];
- for (int i = 0; i < mTailLength; ++i) {
- float xy = 0;
- for (int j = 0;j < mWindowSize; ++j) {
- xy += mXs[i + j] * ys[j];
- }
- mXYs[i] += xy - records[i];
- records[i] = xy;
- if (mXYs[i] < 0) {
- mXYs[i] = 0;
- }
- }
-
- // Computes correlations from XYs, XXs, and YY.
- float weight = 1.0f / (mYY + 1);
- float correlation = 0;
+ // Compute correlations.
+ float corr2 = 0.0f;
int latency = 0;
- for (int i = 0; i < mTailLength; ++i) {
- float c = mXYs[i] * mXYs[i] * weight / (mXXs[i] + 1);
- if (c > correlation) {
- correlation = c;
+ float varY = mY2Sum - mWeight * mYSum * mYSum;
+ for (int i = mTailLength - 1; i >= 0; --i) {
+ float varX = mX2Sums[i] - mWeight * mXSums[i] * mXSums[i];
+ float cov = mXYSums[i] - mWeight * mXSums[i] * mYSum;
+ float c2 = cov * cov / (varX * varY + 1);
+ if (c2 > corr2) {
+ corr2 = c2;
latency = i;
}
}
+ //LOGI("correlation^2 = %.10f, latency = %d", corr2, latency * mScale);
- correlation = sqrtf(correlation);
- if (correlation > 0.3f) {
- float factor = 1.0f - correlation;
- factor *= factor;
- factor /= 2.0; // suppress harder
+ // Do echo suppression.
+ if (corr2 > 0.1f) {
+ int factor = (corr2 > 1.0f) ? 0 : (1.0f - sqrtf(corr2)) * 4096;
for (int i = 0; i < mSampleCount; ++i) {
- recorded[i] *= factor;
+ recorded[i] = recorded[i] * factor >> 16;
}
}
- //LOGI("latency %5d, correlation %.10f", latency, correlation);
-
// Increase RecordOffset.
++mRecordOffset;
diff --git a/voip/jni/rtp/EchoSuppressor.h b/voip/jni/rtp/EchoSuppressor.h
index 85decf5..2f3b593 100644
--- a/voip/jni/rtp/EchoSuppressor.h
+++ b/voip/jni/rtp/EchoSuppressor.h
@@ -23,11 +23,12 @@
{
public:
// The sampleCount must be power of 2.
- EchoSuppressor(int sampleRate, int sampleCount, int tailLength);
+ EchoSuppressor(int sampleCount, int tailLength);
~EchoSuppressor();
void run(int16_t *playbacked, int16_t *recorded);
private:
+ int mShift;
int mScale;
int mSampleCount;
int mWindowSize;
@@ -35,17 +36,23 @@
int mRecordLength;
int mRecordOffset;
- float *mXs;
- float *mXYs;
- float *mXXs;
- float mYY;
+ uint16_t *mXs;
+ uint32_t *mXSums;
+ uint32_t *mX2Sums;
+ uint16_t *mXRecords;
- float *mXYRecords;
- float *mXXRecords;
- float *mYYRecords;
+ uint32_t mYSum;
+ uint32_t mY2Sum;
+ uint32_t *mYRecords;
+ uint32_t *mY2Records;
- float mLastX;
- float mLastY;
+ uint32_t *mXYSums;
+ uint32_t *mXYRecords;
+
+ int32_t mLastX;
+ int32_t mLastY;
+
+ float mWeight;
};
#endif