Merge "Add OBB flags to support overlays" into gingerbread
diff --git a/api/9.xml b/api/9.xml
index f18623f..46f087f 100644
--- a/api/9.xml
+++ b/api/9.xml
@@ -379555,7 +379555,7 @@
type="java.lang.String"
transient="false"
volatile="false"
- value=""100-Continue""
+ value=""100-continue""
static="true"
final="true"
deprecated="not deprecated"
diff --git a/api/current.xml b/api/current.xml
index f494775..61f5e16 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -403611,7 +403611,7 @@
type="java.lang.String"
transient="false"
volatile="false"
- value=""100-Continue""
+ value=""100-continue""
static="true"
final="true"
deprecated="not deprecated"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c88e086..c96d562 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3298,10 +3298,6 @@
Slog.e(TAG, "Failed to find provider info for " + name);
return null;
}
- if (holder.permissionFailure != null) {
- throw new SecurityException("Permission " + holder.permissionFailure
- + " required for provider " + name);
- }
IContentProvider prov = installProvider(context, holder.provider,
holder.info, true);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e99d4b4..2870c50 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2844,6 +2844,7 @@
boolean returnValue;
boolean hasListeners;
+ boolean changesMade = false;
List<String> keysModified = null;
Set<OnSharedPreferenceChangeListener> listeners = null;
@@ -2857,17 +2858,31 @@
synchronized (this) {
if (mClear) {
- mMap.clear();
+ if (!mMap.isEmpty()) {
+ changesMade = true;
+ mMap.clear();
+ }
mClear = false;
}
for (Entry<String, Object> e : mModified.entrySet()) {
String k = e.getKey();
Object v = e.getValue();
- if (v == this) {
- mMap.remove(k);
+ if (v == this) { // magic value for a removal mutation
+ if (mMap.containsKey(k)) {
+ mMap.remove(k);
+ changesMade = true;
+ }
} else {
- mMap.put(k, v);
+ boolean isSame = false;
+ if (mMap.containsKey(k)) {
+ Object existingValue = mMap.get(k);
+ isSame = existingValue != null && existingValue.equals(v);
+ }
+ if (!isSame) {
+ mMap.put(k, v);
+ changesMade = true;
+ }
}
if (hasListeners) {
@@ -2878,7 +2893,7 @@
mModified.clear();
}
- returnValue = writeFileLocked();
+ returnValue = writeFileLocked(changesMade);
}
if (hasListeners) {
@@ -2923,9 +2938,16 @@
return str;
}
- private boolean writeFileLocked() {
+ private boolean writeFileLocked(boolean changesMade) {
// Rename the current file so it may be used as a backup during the next read
if (mFile.exists()) {
+ if (!changesMade) {
+ // If the file already exists, but no changes were
+ // made to the underlying map, it's wasteful to
+ // re-write the file. Return as if we wrote it
+ // out.
+ return true;
+ }
if (!mBackupFile.exists()) {
if (!mFile.renameTo(mBackupFile)) {
Log.e(TAG, "Couldn't rename file " + mFile
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 81b28b9..416f289 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -326,28 +326,19 @@
/** Information you can retrieve about a particular application. */
public static class ContentProviderHolder implements Parcelable {
public final ProviderInfo info;
- public final String permissionFailure;
public IContentProvider provider;
public boolean noReleaseNeeded;
public ContentProviderHolder(ProviderInfo _info) {
info = _info;
- permissionFailure = null;
}
- public ContentProviderHolder(ProviderInfo _info,
- String _permissionFailure) {
- info = _info;
- permissionFailure = _permissionFailure;
- }
-
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
info.writeToParcel(dest, 0);
- dest.writeString(permissionFailure);
if (provider != null) {
dest.writeStrongBinder(provider.asBinder());
} else {
@@ -369,7 +360,6 @@
private ContentProviderHolder(Parcel source) {
info = ProviderInfo.CREATOR.createFromParcel(source);
- permissionFailure = source.readString();
provider = ContentProviderNative.asInterface(
source.readStrongBinder());
noReleaseNeeded = source.readInt() != 0;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 9b9f796..dc4e9c4 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -86,6 +86,7 @@
private String mReadPermission;
private String mWritePermission;
private PathPermission[] mPathPermissions;
+ private boolean mExported;
private Transport mTransport = new Transport();
@@ -257,9 +258,9 @@
final Context context = getContext();
final String rperm = getReadPermission();
final int pid = Binder.getCallingPid();
- if (rperm == null
+ if (mExported && (rperm == null
|| context.checkPermission(rperm, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
+ == PackageManager.PERMISSION_GRANTED)) {
return;
}
@@ -303,9 +304,9 @@
final Context context = getContext();
final String wperm = getWritePermission();
final int pid = Binder.getCallingPid();
- if (wperm == null
+ if (mExported && (wperm == null
|| context.checkPermission(wperm, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
+ == PackageManager.PERMISSION_GRANTED)) {
return true;
}
@@ -786,6 +787,7 @@
setReadPermission(info.readPermission);
setWritePermission(info.writePermission);
setPathPermissions(info.pathPermissions);
+ mExported = info.exported;
}
ContentProvider.this.onCreate();
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index f72de67..a0abc6c 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1138,9 +1138,9 @@
*/
public static final String SCENE_MODE_BARCODE = "barcode";
- // Values for focus mode settings.
/**
- * Auto-focus mode.
+ * Auto-focus mode. Applications should call {@link
+ * #autoFocus(AutoFocusCallback)} to start the focus in this mode.
*/
public static final String FOCUS_MODE_AUTO = "auto";
@@ -1149,6 +1149,12 @@
* {@link #autoFocus(AutoFocusCallback)} in this mode.
*/
public static final String FOCUS_MODE_INFINITY = "infinity";
+
+ /**
+ * Macro (close-up) focus mode. Applications should call
+ * {@link #autoFocus(AutoFocusCallback)} to start the focus in this
+ * mode.
+ */
public static final String FOCUS_MODE_MACRO = "macro";
/**
@@ -1170,7 +1176,9 @@
* Continuous auto focus mode. The camera continuously tries to focus.
* This is ideal for shooting video or shooting photo of moving object.
* Auto focus starts when the parameter is set. Applications should not
- * call {@link #autoFocus(AutoFocusCallback)} in this mode.
+ * call {@link #autoFocus(AutoFocusCallback)} in this mode. To stop
+ * continuous focus, applications should change the focus mode to other
+ * modes.
*/
public static final String FOCUS_MODE_CONTINUOUS = "continuous";
@@ -1948,6 +1956,7 @@
* @see #FOCUS_MODE_INFINITY
* @see #FOCUS_MODE_MACRO
* @see #FOCUS_MODE_FIXED
+ * @see #FOCUS_MODE_EDOF
* @see #FOCUS_MODE_CONTINUOUS
*/
public String getFocusMode() {
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index f6d237a..d2c3eaa 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1525,7 +1525,22 @@
* Typically the atmospheric pressure is read from a
* {@link Sensor#TYPE_PRESSURE} sensor. The pressure at sea level must be
* known, usually it can be retrieved from airport databases in the
- * vicinity.
+ * vicinity. If unknown, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE}
+ * as an approximation, but absolute altitudes won't be accurate.
+ * </p>
+ * <p>
+ * To calculate altitude differences, you must calculate the difference
+ * between the altitudes at both points. If you don't know the altitude
+ * as sea level, you can use {@link #PRESSURE_STANDARD_ATMOSPHERE} instead,
+ * which will give good results considering the range of pressure typically
+ * involved.
+ * </p>
+ * <p>
+ * <code><ul>
+ * float altitude_difference =
+ * getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point2)
+ * - getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure_at_point1);
+ * </ul></code>
* </p>
*
* @param p0 pressure at sea level
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 214510d..c34cb2f 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -53,6 +53,10 @@
private boolean mEnabled;
private BroadcastReceiver mStateReceiver;
+ // DEFAULT and HIPRI are the same connection. If we're one of these we need to check if
+ // the other is also disconnected before we reset sockets
+ private boolean mIsDefaultOrHipri = false;
+
/**
* Create a new MobileDataStateTracker
* @param context the application context of the caller
@@ -71,6 +75,10 @@
} else {
mApnTypeToWatchFor = mApnType;
}
+ if (netType == ConnectivityManager.TYPE_MOBILE ||
+ netType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
+ mIsDefaultOrHipri = true;
+ }
mPhoneService = null;
if(netType == ConnectivityManager.TYPE_MOBILE) {
@@ -138,6 +146,7 @@
}
private class MobileDataStateReceiver extends BroadcastReceiver {
+ ConnectivityManager mConnectivityManager;
public void onReceive(Context context, Intent intent) {
synchronized(this) {
if (intent.getAction().equals(TelephonyIntents.
@@ -190,7 +199,26 @@
}
setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
- if (mInterfaceName != null) {
+ boolean doReset = true;
+ if (mIsDefaultOrHipri == true) {
+ // both default and hipri must go down before we reset
+ int typeToCheck = (Phone.APN_TYPE_DEFAULT.equals(mApnType) ?
+ ConnectivityManager.TYPE_MOBILE_HIPRI :
+ ConnectivityManager.TYPE_MOBILE);
+ if (mConnectivityManager == null) {
+ mConnectivityManager =
+ (ConnectivityManager)context.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ }
+ if (mConnectivityManager != null) {
+ NetworkInfo info = mConnectivityManager.getNetworkInfo(
+ typeToCheck);
+ if (info != null && info.isConnected() == true) {
+ doReset = false;
+ }
+ }
+ }
+ if (doReset && mInterfaceName != null) {
NetworkUtils.resetConnections(mInterfaceName);
}
// can't do this here - ConnectivityService needs it to clear stuff
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 2ca08ea..402443c 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -990,7 +990,8 @@
}
}) : 0;
long durationDraw =
- (root || (view.mPrivateFlags & View.DRAWN) != 0) ? profileViewOperation(view,
+ (root || !view.willNotDraw() || (view.mPrivateFlags & View.DRAWN) != 0) ? profileViewOperation(
+ view,
new ViewOperation<Object>() {
public Object[] pre() {
final DisplayMetrics metrics =
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index fed55dc..55d11bb 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -103,11 +103,11 @@
}
}
- public int getCurrentRotation() {
+ public int getCurrentRotation(int lastRotation) {
if (mEnabled) {
- return mSensorEventListener.getCurrentRotation();
+ return mSensorEventListener.getCurrentRotation(lastRotation);
}
- return -1;
+ return lastRotation;
}
/**
@@ -153,9 +153,15 @@
private static final int ROTATION_270 = 2;
// Mapping our internal aliases into actual Surface rotation values
- private static final int[] SURFACE_ROTATIONS = new int[] {
+ private static final int[] INTERNAL_TO_SURFACE_ROTATION = new int[] {
Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+ // Mapping Surface rotation values to internal aliases.
+ // We have no constant for Surface.ROTATION_180. That should never happen, but if it
+ // does, we'll arbitrarily choose a mapping.
+ private static final int[] SURFACE_TO_INTERNAL_ROTATION = new int[] {
+ ROTATION_0, ROTATION_90, ROTATION_90, ROTATION_270};
+
// Threshold ranges of orientation angle to transition into other orientation states.
// The first list is for transitions from ROTATION_0, the next for ROTATION_90, etc.
// ROTATE_TO defines the orientation each threshold range transitions to, and must be kept
@@ -243,8 +249,12 @@
return (float) SAMPLING_PERIOD_MS / (timeConstantMs + SAMPLING_PERIOD_MS);
}
- int getCurrentRotation() {
- return SURFACE_ROTATIONS[mRotation];
+ int getCurrentRotation(int lastRotation) {
+ if (mTiltDistrust > 0) {
+ // we really don't know the current orientation, so trust what's currently displayed
+ mRotation = SURFACE_TO_INTERNAL_ROTATION[lastRotation];
+ }
+ return INTERNAL_TO_SURFACE_ROTATION[mRotation];
}
private void calculateNewRotation(float orientation, float tiltAngle) {
@@ -267,7 +277,7 @@
if (localLOGV) Log.i(TAG, " new rotation = " + rotation);
mRotation = rotation;
- mOrientationListener.onOrientationChanged(getCurrentRotation());
+ mOrientationListener.onOrientationChanged(INTERNAL_TO_SURFACE_ROTATION[mRotation]);
}
private float lowpassFilter(float newValue, float oldValue, float alpha) {
@@ -306,7 +316,8 @@
mTiltAngle = lowpassFilter(newTiltAngle, mTiltAngle, alpha);
float absoluteTilt = Math.abs(mTiltAngle);
- if (checkFullyTilted(absoluteTilt)) {
+ checkFullyTilted(absoluteTilt);
+ if (mTiltDistrust > 0) {
return; // when fully tilted, ignore orientation entirely
}
@@ -347,11 +358,9 @@
* get un-tilted.
*
* @param absoluteTilt the absolute value of the current tilt angle
- * @return true if the phone is fully tilted
*/
- private boolean checkFullyTilted(float absoluteTilt) {
- boolean fullyTilted = absoluteTilt > MAX_TILT;
- if (fullyTilted) {
+ private void checkFullyTilted(float absoluteTilt) {
+ if (absoluteTilt > MAX_TILT) {
if (mRotation == ROTATION_0) {
mOrientationAngle = 0;
} else if (mRotation == ROTATION_90) {
@@ -366,7 +375,6 @@
} else if (mTiltDistrust > 0) {
mTiltDistrust--;
}
- return fullyTilted;
}
/**
@@ -389,8 +397,8 @@
*/
private void filterOrientation(float absoluteTilt, float orientationAngle) {
float alpha = DEFAULT_LOWPASS_ALPHA;
- if (mTiltDistrust > 0 || mAccelerationDistrust > 1) {
- // when fully tilted, or under more than a transient acceleration, distrust heavily
+ if (mAccelerationDistrust > 1) {
+ // when under more than a transient acceleration, distrust heavily
alpha = ACCELERATING_LOWPASS_ALPHA;
} else if (absoluteTilt > PARTIAL_TILT || mAccelerationDistrust == 1) {
// when tilted partway, or under transient acceleration, distrust lightly
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 204bb74..578de6f 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -518,35 +518,48 @@
///////////////////////////////////////////////////////////////////////////////
JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM)
- : fEnv(env), fReportSizeToVM(reportSizeToVM) {}
+ : fReportSizeToVM(reportSizeToVM) {
+ if (env->GetJavaVM(&fVM) != JNI_OK) {
+ SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
+ sk_throw();
+ }
+}
bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
- return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable, fReportSizeToVM);
+ JNIEnv* env = vm2env(fVM);
+ return GraphicsJNI::setJavaPixelRef(env, bitmap, ctable, fReportSizeToVM);
}
////////////////////////////////////////////////////////////////////////////////
JavaMemoryUsageReporter::JavaMemoryUsageReporter(JNIEnv* env)
- : fEnv(env), fTotalSize(0) {}
+ : fTotalSize(0) {
+ if (env->GetJavaVM(&fVM) != JNI_OK) {
+ SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
+ sk_throw();
+ }
+}
JavaMemoryUsageReporter::~JavaMemoryUsageReporter() {
+ JNIEnv* env = vm2env(fVM);
jlong jtotalSize = fTotalSize;
- fEnv->CallVoidMethod(gVMRuntime_singleton,
+ env->CallVoidMethod(gVMRuntime_singleton,
gVMRuntime_trackExternalFreeMethodID,
jtotalSize);
}
bool JavaMemoryUsageReporter::reportMemory(size_t memorySize) {
jlong jsize = memorySize; // the VM wants longs for the size
- bool r = fEnv->CallBooleanMethod(gVMRuntime_singleton,
+ JNIEnv* env = vm2env(fVM);
+ bool r = env->CallBooleanMethod(gVMRuntime_singleton,
gVMRuntime_trackExternalAllocationMethodID,
jsize);
- if (GraphicsJNI::hasException(fEnv)) {
+ if (GraphicsJNI::hasException(env)) {
return false;
}
if (!r) {
LOGE("VM won't let us allocate %zd bytes\n", memorySize);
- doThrowOOME(fEnv, "bitmap size exceeds VM budget");
+ doThrowOOME(env, "bitmap size exceeds VM budget");
return false;
}
fTotalSize += memorySize;
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 8d6528b..1a43a3e 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -80,7 +80,7 @@
virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
private:
- JNIEnv* fEnv;
+ JavaVM* fVM;
bool fReportSizeToVM;
};
@@ -92,7 +92,7 @@
virtual bool reportMemory(size_t memorySize);
private:
- JNIEnv* fEnv;
+ JavaVM* fVM;
size_t fTotalSize;
};
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 6a5d254..99a3115 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -337,11 +337,14 @@
static const char PIXEL_FORMAT_JPEG[];
// Values for focus mode settings.
- // Auto-focus mode.
+ // Auto-focus mode. Applications should call
+ // CameraHardwareInterface.autoFocus to start the focus in this mode.
static const char FOCUS_MODE_AUTO[];
// Focus is set at infinity. Applications should not call
// CameraHardwareInterface.autoFocus in this mode.
static const char FOCUS_MODE_INFINITY[];
+ // Macro (close-up) focus mode. Applications should call
+ // CameraHardwareInterface.autoFocus to start the focus in this mode.
static const char FOCUS_MODE_MACRO[];
// Focus is fixed. The camera is always in this mode if the focus is not
// adjustable. If the camera has auto-focus, this mode can fix the
@@ -355,7 +358,8 @@
// Continuous auto focus mode. The camera continuously tries to focus. This
// is ideal for shooting video or shooting photo of moving object. Auto
// focus starts when the parameter is set. Applications should not call
- // CameraHardwareInterface.autoFocus in this mode.
+ // CameraHardwareInterface.autoFocus in this mode. To stop continuous
+ // focus, applications should change the focus mode to other modes.
static const char FOCUS_MODE_CONTINUOUS[];
// The camera determines the exposure by giving more weight to the
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 3132941..3d42856 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -224,6 +224,7 @@
uint8_t* keyBitmask;
KeyLayoutMap* layoutMap;
String8 keylayoutFilename;
+ int fd;
device_t* next;
device_t(int32_t _id, const char* _path, const char* name);
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index 2505cb0..aed4fa1 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -159,6 +159,12 @@
virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid,
Vector<InputTarget>& outTargets) = 0;
+
+ /* Gets the maximum suggested event delivery rate per second.
+ * This value is used to throttle motion event movement actions on a per-device
+ * basis. It is not intended to be a hard limit.
+ */
+ virtual int32_t getMaxEventsPerSecond() = 0;
};
@@ -332,6 +338,8 @@
// Linked list of motion samples associated with this motion event.
MotionSample firstSample;
MotionSample* lastSample;
+
+ uint32_t countSamples() const;
};
// Tracks the progress of dispatching a particular event to a particular connection.
@@ -587,6 +595,17 @@
Condition mInjectionSyncFinishedCondition;
void decrementPendingSyncDispatchesLocked(EventEntry* entry);
+ // Throttling state.
+ struct ThrottleState {
+ nsecs_t minTimeBetweenEvents;
+
+ nsecs_t lastEventTime;
+ int32_t lastDeviceId;
+ uint32_t lastSource;
+
+ uint32_t originalSampleCount; // only collected during debugging
+ } mThrottleState;
+
// Key repeat tracking.
// XXX Move this up to the input reader instead.
struct KeyRepeatState {
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 71c6c51..56d2765 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -480,10 +480,6 @@
inline void clear() {
fields = 0;
}
-
- inline bool isDirty() {
- return fields != 0;
- }
} mAccumulator;
float mXScale;
@@ -702,7 +698,7 @@
} historyData[AVERAGING_HISTORY_SIZE];
} mAveragingTouchFilter;
- struct JumpTouchFilterState {
+ struct JumpyTouchFilterState {
uint32_t jumpyPointsDropped;
} mJumpyTouchFilter;
@@ -765,10 +761,6 @@
inline void clear() {
fields = 0;
}
-
- inline bool isDirty() {
- return fields != 0;
- }
} mAccumulator;
bool mDown;
@@ -804,7 +796,8 @@
FIELD_ABS_MT_WIDTH_MAJOR = 16,
FIELD_ABS_MT_WIDTH_MINOR = 32,
FIELD_ABS_MT_ORIENTATION = 64,
- FIELD_ABS_MT_TRACKING_ID = 128
+ FIELD_ABS_MT_TRACKING_ID = 128,
+ FIELD_ABS_MT_PRESSURE = 256,
};
uint32_t pointerCount;
@@ -819,6 +812,7 @@
int32_t absMTWidthMinor;
int32_t absMTOrientation;
int32_t absMTTrackingId;
+ int32_t absMTPressure;
inline void clear() {
fields = 0;
@@ -829,10 +823,6 @@
pointerCount = 0;
pointers[0].clear();
}
-
- inline bool isDirty() {
- return pointerCount != 0;
- }
} mAccumulator;
void initialize();
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 33393fe..891661d 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -60,7 +60,6 @@
#define ID_MASK 0x0000ffff
#define SEQ_MASK 0x7fff0000
#define SEQ_SHIFT 16
-#define id_to_index(id) ((id&ID_MASK)+1)
#ifndef ABS_MT_TOUCH_MAJOR
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
@@ -87,7 +86,7 @@
EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name)
: id(_id), path(_path), name(name), classes(0)
- , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) {
+ , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), fd(-1), next(NULL) {
}
EventHub::device_t::~device_t() {
@@ -152,9 +151,9 @@
struct input_absinfo info;
- if(ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGABS(axis), &info)) {
+ if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
LOGW("Error reading absolute controller %d for device %s fd %d\n",
- axis, device->name.string(), mFDs[id_to_index(device->id)].fd);
+ axis, device->name.string(), device->fd);
return -errno;
}
@@ -183,7 +182,7 @@
int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
- if (ioctl(mFDs[id_to_index(device->id)].fd,
+ if (ioctl(device->fd,
EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
}
@@ -206,8 +205,7 @@
uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
- if (ioctl(mFDs[id_to_index(device->id)].fd,
- EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
+ if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
#if 0
for (size_t i=0; i<=KEY_MAX; i++) {
LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
@@ -243,7 +241,7 @@
int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
memset(sw_bitmask, 0, sizeof(sw_bitmask));
- if (ioctl(mFDs[id_to_index(device->id)].fd,
+ if (ioctl(device->fd,
EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
}
@@ -583,7 +581,6 @@
if (strcmp(name, test) == 0) {
LOGI("ignoring event id %s driver %s\n", deviceName, test);
close(fd);
- fd = -1;
return -1;
}
}
@@ -657,6 +654,7 @@
return -1;
}
+ device->fd = fd;
mFDs[mFDCount].fd = fd;
mFDs[mFDCount].events = POLLIN;
mFDs[mFDCount].revents = 0;
@@ -814,6 +812,14 @@
device->id, name, propName, keylayoutFilename);
}
+ // If the device isn't recognized as something we handle, don't monitor it.
+ if (device->classes == 0) {
+ LOGV("Dropping device %s %p, id = %d\n", deviceName, device, devid);
+ close(fd);
+ delete device;
+ return -1;
+ }
+
LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 13030b5..ce616a4 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -28,6 +28,9 @@
// Log debug messages about input event injection.
#define DEBUG_INJECTION 0
+// Log debug messages about input event throttling.
+#define DEBUG_THROTTLING 0
+
#include <cutils/log.h>
#include <ui/InputDispatcher.h>
@@ -66,6 +69,15 @@
mKeyRepeatState.lastKeyEntry = NULL;
+ int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
+ mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
+ mThrottleState.lastDeviceId = -1;
+
+#if DEBUG_THROTTLING
+ mThrottleState.originalSampleCount = 0;
+ LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
+#endif
+
mCurrentInputTargetsValid = false;
}
@@ -144,12 +156,60 @@
}
} else {
// Inbound queue has at least one entry.
- // Start processing it but leave it on the queue until later so that the
+ EventEntry* entry = mInboundQueue.head.next;
+
+ // Consider throttling the entry if it is a move event and there are no
+ // other events behind it in the queue. Due to movement batching, additional
+ // samples may be appended to this event by the time the throttling timeout
+ // expires.
+ // TODO Make this smarter and consider throttling per device independently.
+ if (entry->type == EventEntry::TYPE_MOTION) {
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+ int32_t deviceId = motionEntry->deviceId;
+ uint32_t source = motionEntry->source;
+ if (motionEntry->next == & mInboundQueue.tail
+ && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
+ && deviceId == mThrottleState.lastDeviceId
+ && source == mThrottleState.lastSource) {
+ nsecs_t nextTime = mThrottleState.lastEventTime
+ + mThrottleState.minTimeBetweenEvents;
+ if (currentTime < nextTime) {
+ // Throttle it!
+#if DEBUG_THROTTLING
+ LOGD("Throttling - Delaying motion event for "
+ "device 0x%x, source 0x%08x by up to %0.3fms.",
+ deviceId, source, (nextTime - currentTime) * 0.000001);
+#endif
+ if (nextTime < nextWakeupTime) {
+ nextWakeupTime = nextTime;
+ }
+ if (mThrottleState.originalSampleCount == 0) {
+ mThrottleState.originalSampleCount =
+ motionEntry->countSamples();
+ }
+ goto Throttle;
+ }
+ }
+
+#if DEBUG_THROTTLING
+ if (mThrottleState.originalSampleCount != 0) {
+ uint32_t count = motionEntry->countSamples();
+ LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
+ count - mThrottleState.originalSampleCount,
+ mThrottleState.originalSampleCount, count);
+ mThrottleState.originalSampleCount = 0;
+ }
+#endif
+
+ mThrottleState.lastEventTime = currentTime;
+ mThrottleState.lastDeviceId = deviceId;
+ mThrottleState.lastSource = source;
+ }
+
+ // Start processing the entry but leave it on the queue until later so that the
// input reader can keep appending samples onto a motion event between the
// time we started processing it and the time we finally enqueue dispatch
// entries for it.
- EventEntry* entry = mInboundQueue.head.next;
-
switch (entry->type) {
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
@@ -179,6 +239,8 @@
mInboundQueue.dequeue(entry);
mAllocator.releaseEventEntry(entry);
skipPoll = true;
+
+ Throttle: ;
}
}
@@ -192,8 +254,8 @@
return;
}
- // Wait for callback or timeout or wake.
- nsecs_t timeout = nanoseconds_to_milliseconds(nextWakeupTime - currentTime);
+ // Wait for callback or timeout or wake. (make sure we round up, not down)
+ nsecs_t timeout = (nextWakeupTime - currentTime + 999999LL) / 1000000LL;
int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
mPollLoop->pollOnce(timeoutMillis);
}
@@ -1708,6 +1770,16 @@
motionEntry->lastSample = sample;
}
+// --- InputDispatcher::MotionEntry ---
+
+uint32_t InputDispatcher::MotionEntry::countSamples() const {
+ uint32_t count = 1;
+ for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
+ count += 1;
+ }
+ return count;
+}
+
// --- InputDispatcher::Connection ---
InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 5f5a4ac..6f042ec 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -945,7 +945,6 @@
mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
mAccumulator.btnMouse = false;
sync(when);
- mAccumulator.clear();
}
InputMapper::reset();
@@ -958,9 +957,9 @@
case BTN_MOUSE:
mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
mAccumulator.btnMouse = rawEvent->value != 0;
-
+ // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
+ // we need to ensure that we report the up/down promptly.
sync(rawEvent->when);
- mAccumulator.clear();
break;
}
break;
@@ -981,10 +980,7 @@
case EV_SYN:
switch (rawEvent->scanCode) {
case SYN_REPORT:
- if (mAccumulator.isDirty()) {
- sync(rawEvent->when);
- mAccumulator.clear();
- }
+ sync(rawEvent->when);
break;
}
break;
@@ -992,13 +988,17 @@
}
void TrackballInputMapper::sync(nsecs_t when) {
+ uint32_t fields = mAccumulator.fields;
+ if (fields == 0) {
+ return; // no new state changes, so nothing to do
+ }
+
int motionEventAction;
PointerCoords pointerCoords;
nsecs_t downTime;
{ // acquire lock
AutoMutex _l(mLock);
- uint32_t fields = mAccumulator.fields;
bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
if (downChanged) {
@@ -1061,6 +1061,8 @@
} // release lock
applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
+
+ mAccumulator.clear();
}
void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
@@ -2380,8 +2382,8 @@
mDown = false;
mX = 0;
mY = 0;
- mPressure = 0;
- mSize = 0;
+ mPressure = 1; // default to 1 for devices that don't report pressure
+ mSize = 0; // default to 0 for devices that don't report size
}
void SingleTouchInputMapper::reset() {
@@ -2397,9 +2399,9 @@
case BTN_TOUCH:
mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
mAccumulator.btnTouch = rawEvent->value != 0;
-
- sync(rawEvent->when);
- mAccumulator.clear();
+ // Don't sync immediately. Wait until the next SYN_REPORT since we might
+ // not have received valid position information yet. This logic assumes that
+ // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
break;
}
break;
@@ -2428,10 +2430,7 @@
case EV_SYN:
switch (rawEvent->scanCode) {
case SYN_REPORT:
- if (mAccumulator.isDirty()) {
- sync(rawEvent->when);
- mAccumulator.clear();
- }
+ sync(rawEvent->when);
break;
}
break;
@@ -2439,9 +2438,10 @@
}
void SingleTouchInputMapper::sync(nsecs_t when) {
- /* Update device state */
-
uint32_t fields = mAccumulator.fields;
+ if (fields == 0) {
+ return; // no new state changes, so nothing to do
+ }
if (fields & Accumulator::FIELD_BTN_TOUCH) {
mDown = mAccumulator.btnTouch;
@@ -2472,8 +2472,8 @@
mCurrentTouch.pointers[0].y = mY;
mCurrentTouch.pointers[0].pressure = mPressure;
mCurrentTouch.pointers[0].size = mSize;
- mCurrentTouch.pointers[0].touchMajor = mPressure;
- mCurrentTouch.pointers[0].touchMinor = mPressure;
+ mCurrentTouch.pointers[0].touchMajor = mSize;
+ mCurrentTouch.pointers[0].touchMinor = mSize;
mCurrentTouch.pointers[0].toolMajor = mSize;
mCurrentTouch.pointers[0].toolMinor = mSize;
mCurrentTouch.pointers[0].orientation = 0;
@@ -2482,6 +2482,8 @@
}
syncTouch(when, true);
+
+ mAccumulator.clear();
}
void SingleTouchInputMapper::configureAxes() {
@@ -2494,8 +2496,8 @@
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size);
- mAxes.touchMajor = mAxes.pressure;
- mAxes.touchMinor = mAxes.pressure;
+ mAxes.touchMajor = mAxes.size;
+ mAxes.touchMinor = mAxes.size;
mAxes.toolMajor = mAxes.size;
mAxes.toolMinor = mAxes.size;
}
@@ -2585,10 +2587,7 @@
}
case SYN_REPORT:
- if (mAccumulator.isDirty()) {
- sync(rawEvent->when);
- mAccumulator.clear();
- }
+ sync(rawEvent->when);
break;
}
break;
@@ -2598,11 +2597,7 @@
void MultiTouchInputMapper::sync(nsecs_t when) {
static const uint32_t REQUIRED_FIELDS =
Accumulator::FIELD_ABS_MT_POSITION_X
- | Accumulator::FIELD_ABS_MT_POSITION_Y
- | Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
- | Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
-
- /* Update device state */
+ | Accumulator::FIELD_ABS_MT_POSITION_Y;
uint32_t inCount = mAccumulator.pointerCount;
uint32_t outCount = 0;
@@ -2611,53 +2606,76 @@
mCurrentTouch.clear();
for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
- uint32_t fields = mAccumulator.pointers[inIndex].fields;
+ const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
+ uint32_t fields = inPointer.fields;
if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
-#if DEBUG_POINTERS
- LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
- inIndex, fields);
- continue;
-#endif
- }
-
- if (mAccumulator.pointers[inIndex].absMTTouchMajor <= 0) {
- // Pointer is not down. Drop it.
+ // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
+ // Drop this finger.
continue;
}
- mCurrentTouch.pointers[outCount].x = mAccumulator.pointers[inIndex].absMTPositionX;
- mCurrentTouch.pointers[outCount].y = mAccumulator.pointers[inIndex].absMTPositionY;
+ PointerData& outPointer = mCurrentTouch.pointers[outCount];
+ outPointer.x = inPointer.absMTPositionX;
+ outPointer.y = inPointer.absMTPositionY;
- mCurrentTouch.pointers[outCount].touchMajor =
- mAccumulator.pointers[inIndex].absMTTouchMajor;
- mCurrentTouch.pointers[outCount].touchMinor =
- (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0
- ? mAccumulator.pointers[inIndex].absMTTouchMinor
- : mAccumulator.pointers[inIndex].absMTTouchMajor;
+ if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
+ int32_t value = inPointer.absMTTouchMajor;
+ if (value <= 0) {
+ // Some devices send sync packets with X / Y but with a 0 touch major to indicate
+ // a pointer up. Drop this finger.
+ continue;
+ }
+ outPointer.touchMajor = inPointer.absMTTouchMajor;
+ } else {
+ outPointer.touchMajor = 0;
+ }
- mCurrentTouch.pointers[outCount].toolMajor =
- mAccumulator.pointers[inIndex].absMTWidthMajor;
- mCurrentTouch.pointers[outCount].toolMinor =
- (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0
- ? mAccumulator.pointers[inIndex].absMTWidthMinor
- : mAccumulator.pointers[inIndex].absMTWidthMajor;
+ if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
+ outPointer.touchMinor = inPointer.absMTTouchMinor;
+ } else {
+ outPointer.touchMinor = outPointer.touchMajor;
+ }
- mCurrentTouch.pointers[outCount].orientation =
- (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) != 0
- ? mAccumulator.pointers[inIndex].absMTOrientation : 0;
+ if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
+ outPointer.toolMajor = inPointer.absMTWidthMajor;
+ } else {
+ outPointer.toolMajor = outPointer.touchMajor;
+ }
- // Derive an approximation of pressure and size.
- // FIXME assignment of pressure may be incorrect, probably better to let
- // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
- // isn't quite right either. Should be using touch for that.
- mCurrentTouch.pointers[outCount].pressure = mAccumulator.pointers[inIndex].absMTTouchMajor;
- mCurrentTouch.pointers[outCount].size = mAccumulator.pointers[inIndex].absMTWidthMajor;
+ if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
+ outPointer.toolMinor = inPointer.absMTWidthMinor;
+ } else {
+ outPointer.toolMinor = outPointer.toolMajor;
+ }
+
+ if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
+ outPointer.orientation = inPointer.absMTOrientation;
+ } else {
+ outPointer.orientation = 0;
+ }
+
+ if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
+ outPointer.pressure = inPointer.absMTPressure;
+ } else {
+ // Derive an approximation of pressure.
+ // FIXME Traditionally we have just passed a normalized value based on
+ // ABS_MT_TOUCH_MAJOR as an estimate of pressure but the result is not
+ // very meaningful, particularly on large displays. We should probably let
+ // pressure = touch_major / tool_major but it is unclear whether that will
+ // break applications.
+ outPointer.pressure = outPointer.touchMajor;
+ }
+
+ // Size is an alias for a normalized tool width.
+ // FIXME Normalized tool width doesn't actually make much sense since it literally
+ // means the approaching contact major axis is divided by its full range as
+ // reported by the driver. On a large display this could produce very small values.
+ outPointer.size = outPointer.toolMajor;
if (havePointerIds) {
- if (fields & Accumulator::
- FIELD_ABS_MT_TRACKING_ID) {
- uint32_t id = uint32_t(mAccumulator.pointers[inIndex].absMTTrackingId);
+ if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
+ uint32_t id = uint32_t(inPointer.absMTTrackingId);
if (id > MAX_POINTER_ID) {
#if DEBUG_POINTERS
@@ -2668,7 +2686,7 @@
havePointerIds = false;
}
else {
- mCurrentTouch.pointers[outCount].id = id;
+ outPointer.id = id;
mCurrentTouch.idToIndex[id] = outCount;
mCurrentTouch.idBits.markBit(id);
}
@@ -2683,6 +2701,8 @@
mCurrentTouch.pointerCount = outCount;
syncTouch(when, havePointerIds);
+
+ mAccumulator.clear();
}
void MultiTouchInputMapper::configureAxes() {
@@ -2697,6 +2717,7 @@
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation);
+ getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mAxes.pressure);
if (! mAxes.touchMinor.valid) {
mAxes.touchMinor = mAxes.touchMajor;
@@ -2706,7 +2727,10 @@
mAxes.toolMinor = mAxes.toolMajor;
}
- mAxes.pressure = mAxes.touchMajor;
+ if (! mAxes.pressure.valid) {
+ mAxes.pressure = mAxes.touchMajor;
+ }
+
mAxes.size = mAxes.toolMajor;
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 6af3a7f..12a1e6e 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1273,6 +1273,14 @@
hexdump(csd, csd_size);
#endif
+ if (csd_size == 0) {
+ // There's no further information, i.e. no codec specific data
+ // Let's assume that the information provided in the mpeg4 headers
+ // is accurate and hope for the best.
+
+ return OK;
+ }
+
if (csd_size < 2) {
return ERROR_MALFORMED;
}
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index b699d8f..9630092 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -158,7 +158,7 @@
ReadOptions::SeekMode mode;
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll;
- LOGI("seeking to offset %ld", pos);
+ LOGV("seeking to offset %ld", pos);
if (mExtractor->mImpl->seekToOffset(pos) != OK) {
return ERROR_END_OF_STREAM;
@@ -267,7 +267,7 @@
uint8_t header[27];
if (mSource->readAt(offset, header, sizeof(header))
< (ssize_t)sizeof(header)) {
- LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset);
+ LOGV("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset);
return ERROR_IO;
}
@@ -384,7 +384,7 @@
packetSize);
if (n < (ssize_t)packetSize) {
- LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset);
+ LOGV("failed to read %d bytes at 0x%08lx", packetSize, dataOffset);
return ERROR_IO;
}
@@ -418,7 +418,7 @@
buffer = NULL;
}
- LOGE("readPage returned %ld", n);
+ LOGV("readPage returned %ld", n);
return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
}
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 224b4bf..b2d697b 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -18,6 +18,8 @@
#include "ASessionDescription.h"
+#include <ctype.h>
+
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -37,6 +39,10 @@
size_t keyLen = strlen(key);
for (;;) {
+ while (isspace(*s)) {
+ ++s;
+ }
+
const char *colonPos = strchr(s, ';');
size_t len =
@@ -253,7 +259,11 @@
mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
int32_t width, height;
- sessionDesc->getDimensions(index, PT, &width, &height);
+ if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
+ // TODO: extract dimensions from sequence parameter set.
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
mFormat->setInt32(kKeyWidth, width);
mFormat->setInt32(kKeyHeight, height);
@@ -271,7 +281,10 @@
mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
int32_t width, height;
- sessionDesc->getDimensions(index, PT, &width, &height);
+ if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
mFormat->setInt32(kKeyWidth, width);
mFormat->setInt32(kKeyHeight, height);
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index e9162c0..5f8f5fd 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -136,6 +136,20 @@
return true;
}
+static void MakeSocketBlocking(int s, bool blocking) {
+ // Make socket non-blocking.
+ int flags = fcntl(s, F_GETFL, 0);
+ CHECK_NE(flags, -1);
+
+ if (blocking) {
+ flags &= ~O_NONBLOCK;
+ } else {
+ flags |= O_NONBLOCK;
+ }
+
+ CHECK_NE(fcntl(s, F_SETFL, flags), -1);
+}
+
void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
++mConnectionID;
@@ -150,10 +164,7 @@
mSocket = socket(AF_INET, SOCK_STREAM, 0);
- // Make socket non-blocking.
- int flags = fcntl(mSocket, F_GETFL, 0);
- CHECK_NE(flags, -1);
- CHECK_NE(fcntl(mSocket, F_SETFL, flags | O_NONBLOCK), -1);
+ MakeSocketBlocking(mSocket, false);
AString url;
CHECK(msg->findString("url", &url));
@@ -210,7 +221,7 @@
mSocket = -1;
flushPendingRequests();
- }
+ }
sp<AMessage> reply;
CHECK(msg->findMessage("reply", &reply));
@@ -347,7 +358,13 @@
CHECK_GE(res, 0);
if (res == 1) {
- if (!receiveRTSPReponse()) {
+ MakeSocketBlocking(mSocket, true);
+
+ bool success = receiveRTSPReponse();
+
+ MakeSocketBlocking(mSocket, false);
+
+ if (!success) {
// Something horrible, irreparable has happened.
flushPendingRequests();
return;
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index ad813cd..4ea7fda 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -203,13 +203,18 @@
}
}
-void ASessionDescription::getDimensions(
+bool ASessionDescription::getDimensions(
size_t index, unsigned long PT,
int32_t *width, int32_t *height) const {
+ *width = 0;
+ *height = 0;
+
char key[20];
sprintf(key, "a=framesize:%lu", PT);
AString value;
- CHECK(findAttribute(index, key, &value));
+ if (!findAttribute(index, key, &value)) {
+ return false;
+ }
const char *s = value.c_str();
char *end;
@@ -221,6 +226,8 @@
*height = strtoul(s, &end, 10);
CHECK_GT(end, s);
CHECK_EQ(*end, '\0');
+
+ return true;
}
bool ASessionDescription::getDurationUs(int64_t *durationUs) const {
diff --git a/media/libstagefright/rtsp/ASessionDescription.h b/media/libstagefright/rtsp/ASessionDescription.h
index b26980f..a3fa79e 100644
--- a/media/libstagefright/rtsp/ASessionDescription.h
+++ b/media/libstagefright/rtsp/ASessionDescription.h
@@ -44,7 +44,7 @@
size_t index, unsigned long *PT,
AString *desc, AString *params) const;
- void getDimensions(
+ bool getDimensions(
size_t index, unsigned long PT,
int32_t *width, int32_t *height) const;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index f21c8dc..b19ad48 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -309,6 +309,16 @@
size_t trackIndex;
CHECK(msg->findSize("track-index", &trackIndex));
+ int32_t eos;
+ if (msg->findInt32("eos", &eos)) {
+ LOG(INFO) << "received BYE on track index " << trackIndex;
+#if 0
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+ track->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
+#endif
+ return;
+ }
+
sp<RefBase> obj;
CHECK(msg->findObject("access-unit", &obj));
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 5bbe441..9e25681 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -576,41 +576,44 @@
buffer = 0;
// dequeue a new buffer
- nativeWindow->dequeueBuffer(nativeWindow, &buffer);
-
- // TODO: lockBuffer should rather be executed when the very first
- // direct rendering occurs.
- nativeWindow->lockBuffer(nativeWindow, buffer);
-
- // reallocate the depth-buffer if needed
- if ((width != buffer->width) || (height != buffer->height)) {
- // TODO: we probably should reset the swap rect here
- // if the window size has changed
- width = buffer->width;
- height = buffer->height;
- if (depth.data) {
- free(depth.data);
- depth.width = width;
- depth.height = height;
- depth.stride = buffer->stride;
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
- if (depth.data == 0) {
- setError(EGL_BAD_ALLOC, EGL_FALSE);
- return EGL_FALSE;
+ if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {
+
+ // TODO: lockBuffer should rather be executed when the very first
+ // direct rendering occurs.
+ nativeWindow->lockBuffer(nativeWindow, buffer);
+
+ // reallocate the depth-buffer if needed
+ if ((width != buffer->width) || (height != buffer->height)) {
+ // TODO: we probably should reset the swap rect here
+ // if the window size has changed
+ width = buffer->width;
+ height = buffer->height;
+ if (depth.data) {
+ free(depth.data);
+ depth.width = width;
+ depth.height = height;
+ depth.stride = buffer->stride;
+ depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ if (depth.data == 0) {
+ setError(EGL_BAD_ALLOC, EGL_FALSE);
+ return EGL_FALSE;
+ }
}
}
- }
-
- // keep a reference on the buffer
- buffer->common.incRef(&buffer->common);
- // finally pin the buffer down
- if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
- LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
- buffer, buffer->width, buffer->height);
- return setError(EGL_BAD_ACCESS, EGL_FALSE);
- // FIXME: we should make sure we're not accessing the buffer anymore
+ // keep a reference on the buffer
+ buffer->common.incRef(&buffer->common);
+
+ // finally pin the buffer down
+ if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+ LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+ buffer, buffer->width, buffer->height);
+ return setError(EGL_BAD_ACCESS, EGL_FALSE);
+ // FIXME: we should make sure we're not accessing the buffer anymore
+ }
+ } else {
+ return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
}
return EGL_TRUE;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e2e6f1a..274124b 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2076,9 +2076,7 @@
return mDeskDockRotation;
} else {
if (useSensorForOrientationLp(orientation)) {
- // If the user has enabled auto rotation by default, do it.
- int curRotation = mOrientationListener.getCurrentRotation();
- return curRotation >= 0 ? curRotation : lastRotation;
+ return mOrientationListener.getCurrentRotation(lastRotation);
}
return Surface.ROTATION_0;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 6e7633e..ff31470 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1601,7 +1601,7 @@
}
if (mSuspended) {
- sleepTime = idleSleepTime;
+ sleepTime = suspendSleepTimeUs();
}
// sleepTime == 0 means we must write to audio hardware
if (sleepTime == 0) {
@@ -2021,6 +2021,11 @@
return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
}
+uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
+{
+ return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
: PlaybackThread(audioFlinger, output, id, device)
@@ -2365,7 +2370,7 @@
}
if (mSuspended) {
- sleepTime = idleSleepTime;
+ sleepTime = suspendSleepTimeUs();
}
// sleepTime == 0 means we must write to audio hardware
if (sleepTime == 0) {
@@ -2486,6 +2491,18 @@
return time;
}
+uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
+{
+ uint32_t time;
+ if (AudioSystem::isLinearPCM(mFormat)) {
+ time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
+ } else {
+ time = 10000;
+ }
+ return time;
+}
+
+
// ----------------------------------------------------------------------------
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
@@ -2612,7 +2629,7 @@
}
if (mSuspended) {
- sleepTime = idleSleepTime;
+ sleepTime = suspendSleepTimeUs();
}
// sleepTime == 0 means we must write to audio hardware
if (sleepTime == 0) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 5520551..51881f0 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -664,6 +664,7 @@
virtual void deleteTrackName_l(int name) = 0;
virtual uint32_t activeSleepTimeUs() = 0;
virtual uint32_t idleSleepTimeUs() = 0;
+ virtual uint32_t suspendSleepTimeUs() = 0;
private:
@@ -724,6 +725,7 @@
virtual void deleteTrackName_l(int name);
virtual uint32_t activeSleepTimeUs();
virtual uint32_t idleSleepTimeUs();
+ virtual uint32_t suspendSleepTimeUs();
AudioMixer* mAudioMixer;
};
@@ -744,6 +746,7 @@
virtual void deleteTrackName_l(int name);
virtual uint32_t activeSleepTimeUs();
virtual uint32_t idleSleepTimeUs();
+ virtual uint32_t suspendSleepTimeUs();
private:
void applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp);
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index c2c799b..f330d40 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -26,6 +26,7 @@
import android.os.Environment;
import android.os.LocalPowerManager;
import android.os.PowerManager;
+import android.os.SystemProperties;
import android.util.Slog;
import android.util.Xml;
import android.view.InputChannel;
@@ -47,9 +48,6 @@
/*
* Wraps the C++ InputManager and provides its callbacks.
- *
- * XXX Tempted to promote this to a first-class service, ie. InputManagerService, to
- * improve separation of concerns with respect to the window manager.
*/
public class InputManager {
static final String TAG = "InputManager";
@@ -507,5 +505,18 @@
return names.toArray(new String[names.size()]);
}
+
+ @SuppressWarnings("unused")
+ public int getMaxEventsPerSecond() {
+ int result = 0;
+ try {
+ result = Integer.parseInt(SystemProperties.get("windowsmgr.max_events_per_sec"));
+ } catch (NumberFormatException e) {
+ }
+ if (result < 1) {
+ result = 60;
+ }
+ return result;
+ }
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 4762ddb..9d31502 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1162,7 +1162,7 @@
} catch (RemoteException e) {
}
} catch (NameNotFoundException e) {
- Log.w(TAG, "Unable to create context for heavy notification", e);
+ Slog.w(TAG, "Unable to create context for heavy notification", e);
}
} break;
case CANCEL_HEAVY_NOTIFICATION_MSG: {
@@ -2367,7 +2367,7 @@
}
if (proc == null) {
- Log.w(TAG, "crashApplication: nothing for uid=" + uid
+ Slog.w(TAG, "crashApplication: nothing for uid=" + uid
+ " initialPid=" + initialPid
+ " packageName=" + packageName);
return;
@@ -4051,6 +4051,9 @@
return false;
}
}
+ if (!pi.exported && pi.applicationInfo.uid != uid) {
+ return false;
+ }
return true;
} catch (RemoteException e) {
return false;
@@ -4199,8 +4202,8 @@
if (perm == null) {
perm = new UriPermission(targetUid, uri);
targetUris.put(uri, perm);
-
}
+
perm.modeFlags |= modeFlags;
if (activity == null) {
perm.globalModeFlags |= modeFlags;
@@ -4221,6 +4224,11 @@
void grantUriPermissionFromIntentLocked(int callingUid,
String targetPkg, Intent intent, ActivityRecord activity) {
+ if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+ "Grant URI perm to " + (intent != null ? intent.getData() : null)
+ + " from " + intent + "; flags=0x"
+ + Integer.toHexString(intent != null ? intent.getFlags() : 0));
+
if (intent == null) {
return;
}
@@ -4899,13 +4907,12 @@
}
private final String checkContentProviderPermissionLocked(
- ProviderInfo cpi, ProcessRecord r, int mode) {
+ ProviderInfo cpi, ProcessRecord r) {
final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
cpi.exported ? -1 : cpi.applicationInfo.uid)
- == PackageManager.PERMISSION_GRANTED
- && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
+ == PackageManager.PERMISSION_GRANTED) {
return null;
}
if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
@@ -4922,8 +4929,7 @@
PathPermission pp = pps[i];
if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
cpi.exported ? -1 : cpi.applicationInfo.uid)
- == PackageManager.PERMISSION_GRANTED
- && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
+ == PackageManager.PERMISSION_GRANTED) {
return null;
}
if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
@@ -4934,6 +4940,15 @@
}
}
+ HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+ if (perms != null) {
+ for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
+ if (uri.getKey().getAuthority().equals(cpi.authority)) {
+ return null;
+ }
+ }
+ }
+
String msg = "Permission Denial: opening provider " + cpi.name
+ " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
+ ", uid=" + callingUid + ") requires "
@@ -4963,10 +4978,9 @@
cpr = mProvidersByName.get(name);
if (cpr != null) {
cpi = cpr.info;
- if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
- return new ContentProviderHolder(cpi,
- cpi.readPermission != null
- ? cpi.readPermission : cpi.writePermission);
+ String msg;
+ if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
+ throw new SecurityException(msg);
}
if (r != null && cpr.canRunHere(r)) {
@@ -5026,10 +5040,9 @@
return null;
}
- if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
- return new ContentProviderHolder(cpi,
- cpi.readPermission != null
- ? cpi.readPermission : cpi.writePermission);
+ String msg;
+ if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
+ throw new SecurityException(msg);
}
if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
@@ -6180,7 +6193,7 @@
Binder.restoreCallingIdentity(origId);
}
int res = result.get();
- Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
+ Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
}
}
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index ba58b43..3addc0d 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -139,6 +139,7 @@
jmethodID filterJumpyTouchEvents;
jmethodID getVirtualKeyDefinitions;
jmethodID getExcludedDeviceNames;
+ jmethodID getMaxEventsPerSecond;
} gCallbacksClassInfo;
static struct {
@@ -249,6 +250,7 @@
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets);
+ virtual int32_t getMaxEventsPerSecond();
private:
struct InputWindow {
@@ -310,6 +312,9 @@
int32_t mFilterTouchEvents;
int32_t mFilterJumpyTouchEvents;
+ // Cached throttling policy.
+ int32_t mMaxEventsPerSecond;
+
// Cached display state. (lock mDisplayLock)
Mutex mDisplayLock;
int32_t mDisplayWidth, mDisplayHeight;
@@ -400,6 +405,7 @@
NativeInputManager::NativeInputManager(jobject callbacksObj) :
mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
+ mMaxEventsPerSecond(-1),
mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0),
mDispatchEnabled(true), mDispatchFrozen(false), mWindowsReady(true),
mFocusedWindow(NULL), mTouchDown(false), mTouchedWindow(NULL),
@@ -921,6 +927,21 @@
}
}
+int32_t NativeInputManager::getMaxEventsPerSecond() {
+ if (mMaxEventsPerSecond < 0) {
+ JNIEnv* env = jniEnv();
+
+ jint result = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.getMaxEventsPerSecond);
+ if (checkAndClearExceptionFromCallback(env, "getMaxEventsPerSecond")) {
+ result = 60;
+ }
+
+ mMaxEventsPerSecond = result;
+ }
+ return mMaxEventsPerSecond;
+}
+
void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
#if DEBUG_FOCUS
LOGD("setInputWindows");
@@ -2293,6 +2314,9 @@
GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
"getExcludedDeviceNames", "()[Ljava/lang/String;");
+ GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
+ "getMaxEventsPerSecond", "()I");
+
// VirtualKeyDefinition
FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 79772ed..a14bfb5 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -5,7 +5,6 @@
clz.cpp.arm \
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
- DisplayHardware/HWComposer.cpp \
BlurFilter.cpp.arm \
GLExtensions.cpp \
Layer.cpp \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 166c528..2eac0a8 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -36,11 +36,11 @@
#include "DisplayHardware/DisplayHardware.h"
+#include <hardware/copybit.h>
#include <hardware/overlay.h>
#include <hardware/gralloc.h>
#include "GLExtensions.h"
-#include "HWComposer.h"
using namespace android;
@@ -76,7 +76,7 @@
const sp<SurfaceFlinger>& flinger,
uint32_t dpy)
: DisplayHardwareBase(flinger, dpy),
- mFlags(0), mHwc(0)
+ mFlags(0)
{
init(dpy);
}
@@ -262,17 +262,6 @@
// Unbind the context from this thread
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-
- // initialize the H/W composer
- mHwc = new HWComposer();
- if (mHwc->initCheck() == NO_ERROR) {
- mHwc->setFrameBuffer(mDisplay, mSurface);
- }
-}
-
-HWComposer& DisplayHardware::getHwComposer() const {
- return *mHwc;
}
/*
@@ -328,12 +317,7 @@
}
mPageFlipCount++;
-
- if (mHwc->initCheck() == NO_ERROR) {
- mHwc->commit();
- } else {
- eglSwapBuffers(dpy, surface);
- }
+ eglSwapBuffers(dpy, surface);
checkEGLErrors("eglSwapBuffers");
// for debugging
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index f2cfd2d..66bf521 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -34,11 +34,12 @@
#include "DisplayHardware/DisplayHardwareBase.h"
struct overlay_control_device_t;
+struct framebuffer_device_t;
+struct copybit_image_t;
namespace android {
class FramebufferNativeWindow;
-class HWComposer;
class DisplayHardware : public DisplayHardwareBase
{
@@ -79,9 +80,6 @@
uint32_t getPageFlipCount() const;
EGLDisplay getEGLDisplay() const { return mDisplay; }
overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
-
- // Hardware Composer
- HWComposer& getHwComposer() const;
status_t compositionComplete() const;
@@ -109,8 +107,6 @@
GLint mMaxViewportDims;
GLint mMaxTextureSize;
- HWComposer* mHwc;
-
sp<FramebufferNativeWindow> mNativeWindow;
overlay_control_device_t* mOverlayEngine;
};
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
deleted file mode 100644
index 0291d78..0000000
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include <hardware/hardware.h>
-
-#include <cutils/log.h>
-
-#include <EGL/egl.h>
-
-#include "HWComposer.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-HWComposer::HWComposer()
- : mModule(0), mHwc(0), mList(0), mCapacity(0),
- mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
-{
- int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
- LOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
- if (err == 0) {
- err = hwc_open(mModule, &mHwc);
- LOGE_IF(err, "%s device failed to initialize (%s)",
- HWC_HARDWARE_COMPOSER, strerror(-err));
- }
-}
-
-HWComposer::~HWComposer() {
- free(mList);
- if (mHwc) {
- hwc_close(mHwc);
- }
-}
-
-status_t HWComposer::initCheck() const {
- return mHwc ? NO_ERROR : NO_INIT;
-}
-
-void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
- mDpy = (hwc_display_t)dpy;
- mSur = (hwc_surface_t)sur;
-}
-
-status_t HWComposer::createWorkList(size_t numLayers) {
- if (mHwc) {
- if (!mList || mCapacity < numLayers) {
- free(mList);
- size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
- mList = (hwc_layer_list_t*)malloc(size);
- mCapacity = numLayers;
- }
- mList->flags = HWC_GEOMETRY_CHANGED;
- mList->numHwLayers = numLayers;
- }
- return NO_ERROR;
-}
-
-status_t HWComposer::prepare() const {
- int err = mHwc->prepare(mHwc, mList);
- return (status_t)err;
-}
-
-status_t HWComposer::commit() const {
- int err = mHwc->set(mHwc, mDpy, mSur, mList);
- mList->flags &= ~HWC_GEOMETRY_CHANGED;
- return (status_t)err;
-}
-
-size_t HWComposer::getNumLayers() const {
- return mList ? mList->numHwLayers : 0;
-}
-
-hwc_layer_t* HWComposer::getLayers() const {
- return mList ? mList->hwLayers : 0;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
deleted file mode 100644
index c5d5c2b..0000000
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_HWCOMPOSER_H
-#define ANDROID_SF_HWCOMPOSER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <EGL/egl.h>
-
-#include <hardware/hwcomposer.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class HWComposer
-{
-public:
-
- HWComposer();
- ~HWComposer();
-
- status_t initCheck() const;
-
- // tells the HAL what the framebuffer is
- void setFrameBuffer(EGLDisplay dpy, EGLSurface sur);
-
- // create a work list for numLayers layer
- status_t createWorkList(size_t numLayers);
-
- // Asks the HAL what it can do
- status_t prepare() const;
-
- // commits the list
- status_t commit() const;
-
-
- size_t getNumLayers() const;
- hwc_layer_t* getLayers() const;
-
-private:
- hw_module_t const* mModule;
- hwc_composer_device_t* mHwc;
- hwc_layer_list_t* mList;
- size_t mCapacity;
- hwc_display_t mDpy;
- hwc_surface_t mSur;
-};
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3720e1669..629d993 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -35,7 +35,6 @@
#include "Layer.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
-#include "DisplayHardware/HWComposer.h"
#define DEBUG_RESIZE 0
@@ -178,62 +177,6 @@
return NO_ERROR;
}
-void Layer::setGeometry(hwc_layer_t* hwcl)
-{
- hwcl->compositionType = HWC_FRAMEBUFFER;
- hwcl->hints = 0;
- hwcl->flags = 0;
- hwcl->transform = 0;
- hwcl->blending = HWC_BLENDING_NONE;
-
- // we can't do alpha-fade with the hwc HAL
- const State& s(drawingState());
- if (s.alpha < 0xFF) {
- hwcl->flags = HWC_SKIP_LAYER;
- return;
- }
-
- // we can only handle simple transformation
- if (mOrientation & Transform::ROT_INVALID) {
- hwcl->flags = HWC_SKIP_LAYER;
- return;
- }
-
- hwcl->transform = mOrientation;
-
- if (needsBlending()) {
- hwcl->blending = mPremultipliedAlpha ?
- HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
- }
-
- hwcl->displayFrame.left = mTransformedBounds.left;
- hwcl->displayFrame.top = mTransformedBounds.top;
- hwcl->displayFrame.right = mTransformedBounds.right;
- hwcl->displayFrame.bottom = mTransformedBounds.bottom;
-
- hwcl->visibleRegionScreen.rects =
- reinterpret_cast<hwc_rect_t const *>(
- visibleRegionScreen.getArray(
- &hwcl->visibleRegionScreen.numRects));
-}
-
-void Layer::setPerFrameData(hwc_layer_t* hwcl) {
- sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
- if (buffer == NULL) {
- // this situation can happen if we ran out of memory for instance.
- // not much we can do. continue to use whatever texture was bound
- // to this context.
- hwcl->handle = NULL;
- return;
- }
- hwcl->handle = const_cast<native_handle_t*>(buffer->handle);
- // TODO: set the crop value properly
- hwcl->sourceCrop.left = 0;
- hwcl->sourceCrop.top = 0;
- hwcl->sourceCrop.right = buffer->width;
- hwcl->sourceCrop.bottom = buffer->height;
-}
-
void Layer::reloadTexture(const Region& dirty)
{
sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 188da6a..e1d283b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -68,8 +68,6 @@
bool isFixedSize() const;
// LayerBase interface
- virtual void setGeometry(hwc_layer_t* hwcl);
- virtual void setPerFrameData(hwc_layer_t* hwcl);
virtual void onDraw(const Region& clip) const;
virtual uint32_t doTransaction(uint32_t transactionFlags);
virtual void lockPageFlip(bool& recomputeVisibleRegions);
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 043d54d..91ac915 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -307,15 +307,6 @@
}
}
-void LayerBase::setGeometry(hwc_layer_t* hwcl) {
- hwcl->flags |= HWC_SKIP_LAYER;
-}
-
-void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
- hwcl->compositionType = HWC_FRAMEBUFFER;
- hwcl->handle = NULL;
-}
-
void LayerBase::draw(const Region& clip) const
{
// reset GL state
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index dd1cd05..22bf857 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -35,8 +35,6 @@
#include <pixelflinger/pixelflinger.h>
-#include <hardware/hwcomposer.h>
-
#include "Transform.h"
namespace android {
@@ -110,10 +108,6 @@
virtual const char* getTypeId() const { return "LayerBase"; }
- virtual void setGeometry(hwc_layer_t* hwcl);
-
- virtual void setPerFrameData(hwc_layer_t* hwcl);
-
/**
* draw - performs some global clipping optimizations
* and calls onDraw().
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d257897..637ae48 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -52,7 +52,6 @@
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
-#include "DisplayHardware/HWComposer.h"
/* ideally AID_GRAPHICS would be in a semi-public header
* or there would be a way to map a user/group name to its id
@@ -77,7 +76,6 @@
mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
mDump("android.permission.DUMP"),
mVisibleRegionsDirty(false),
- mHwWorkListDirty(false),
mDeferReleaseConsole(false),
mFreezeDisplay(false),
mFreezeCount(0),
@@ -370,11 +368,6 @@
// post surfaces (if needed)
handlePageFlip();
- if (UNLIKELY(mHwWorkListDirty)) {
- // build the h/w work list
- handleWorkList();
- }
-
const DisplayHardware& hw(graphicPlane(0).displayHardware());
if (LIKELY(hw.canDraw() && !isFrozen())) {
// repaint the framebuffer (if needed)
@@ -450,7 +443,6 @@
handleTransactionLocked(transactionFlags, ditchedLayers);
mLastTransactionTime = systemTime() - now;
mDebugInTransaction = 0;
- mHwWorkListDirty = true;
// here the transaction has been committed
}
@@ -458,7 +450,6 @@
* Clean-up all layers that went away
* (do this without the lock held)
*/
-
const size_t count = ditchedLayers.size();
for (size_t i=0 ; i<count ; i++) {
if (ditchedLayers[i] != 0) {
@@ -692,8 +683,8 @@
void SurfaceFlinger::handlePageFlip()
{
bool visibleRegions = mVisibleRegionsDirty;
- LayerVector& currentLayers(
- const_cast<LayerVector&>(mDrawingState.layersSortedByZ));
+ LayerVector& currentLayers = const_cast<LayerVector&>(
+ mDrawingState.layersSortedByZ);
visibleRegions |= lockPageFlip(currentLayers);
const DisplayHardware& hw = graphicPlane(0).displayHardware();
@@ -716,7 +707,6 @@
mWormholeRegion = screenRegion.subtract(opaqueRegion);
mVisibleRegionsDirty = false;
- mHwWorkListDirty = true;
}
unlockPageFlip(currentLayers);
@@ -747,20 +737,6 @@
}
}
-void SurfaceFlinger::handleWorkList()
-{
- mHwWorkListDirty = false;
- HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
- if (hwc.initCheck() == NO_ERROR) {
- const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
- const size_t count = currentLayers.size();
- hwc.createWorkList(count);
- hwc_layer_t* const cur(hwc.getLayers());
- for (size_t i=0 ; cur && i<count ; i++) {
- currentLayers[i]->setGeometry(&cur[i]);
- }
- }
-}
void SurfaceFlinger::handleRepaint()
{
@@ -825,72 +801,9 @@
// draw something...
drawWormhole();
}
-
- status_t err = NO_ERROR;
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
- size_t count = layers.size();
-
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- HWComposer& hwc(hw.getHwComposer());
- hwc_layer_t* const cur(hwc.getLayers());
-
- LOGE_IF(cur && hwc.getNumLayers() != count,
- "HAL number of layers (%d) doesn't match surfaceflinger (%d)",
- hwc.getNumLayers(), count);
-
- // just to be extra-safe, use the smallest count
- if (hwc.initCheck() == NO_ERROR) {
- count = count < hwc.getNumLayers() ? count : hwc.getNumLayers();
- }
-
- /*
- * update the per-frame h/w composer data for each layer
- * and build the transparent region of the FB
- */
- Region transparent;
- if (cur) {
- for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer(layers[i]);
- layer->setPerFrameData(&cur[i]);
- if (cur[i].hints & HWC_HINT_CLEAR_FB) {
- if (!(layer->needsBlending())) {
- transparent.orSelf(layer->visibleRegionScreen);
- }
- }
- }
- err = hwc.prepare();
- LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
- }
-
- /*
- * clear the area of the FB that need to be transparent
- */
- transparent.andSelf(dirty);
- if (!transparent.isEmpty()) {
- glClearColor(0,0,0,0);
- Region::const_iterator it = transparent.begin();
- Region::const_iterator const end = transparent.end();
- const int32_t height = hw.getHeight();
- while (it != end) {
- const Rect& r(*it++);
- const GLint sy = height - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glClear(GL_COLOR_BUFFER_BIT);
- }
- }
-
-
- /*
- * and then, render the layers targeted at the framebuffer
- */
- for (size_t i=0 ; i<count ; i++) {
- if (cur) {
- if (!(cur[i].compositionType == HWC_FRAMEBUFFER) ||
- cur[i].flags & HWC_SKIP_LAYER) {
- // skip layers handled by the HAL
- continue;
- }
- }
+ const size_t count = layers.size();
+ for (size_t i=0 ; i<count ; ++i) {
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8e286e5..8ecfc01 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -296,7 +296,6 @@
void handlePageFlip();
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
- void handleWorkList();
void handleRepaint();
void postFramebuffer();
void composeSurfaces(const Region& dirty);
@@ -371,7 +370,6 @@
Region mInvalidRegion;
Region mWormholeRegion;
bool mVisibleRegionsDirty;
- bool mHwWorkListDirty;
bool mDeferReleaseConsole;
bool mFreezeDisplay;
int32_t mFreezeCount;
diff --git a/voip/java/android/net/rtp/AudioGroup.java b/voip/java/android/net/rtp/AudioGroup.java
index dc86082..37cc121 100644
--- a/voip/java/android/net/rtp/AudioGroup.java
+++ b/voip/java/android/net/rtp/AudioGroup.java
@@ -49,27 +49,28 @@
synchronized void add(AudioStream stream, AudioCodec codec, int codecType, int dtmfType) {
if (!mStreams.containsKey(stream)) {
try {
- int id = add(stream.getMode(), stream.dup(),
+ int socket = stream.dup();
+ add(stream.getMode(), socket,
stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(),
codec.name, codec.sampleRate, codec.sampleCount, codecType, dtmfType);
- mStreams.put(stream, id);
+ mStreams.put(stream, socket);
} catch (NullPointerException e) {
throw new IllegalStateException(e);
}
}
}
- private native int add(int mode, int socket, String remoteAddress, int remotePort,
+ private native void add(int mode, int socket, String remoteAddress, int remotePort,
String codecName, int sampleRate, int sampleCount, int codecType, int dtmfType);
synchronized void remove(AudioStream stream) {
- Integer id = mStreams.remove(stream);
- if (id != null) {
- remove(id);
+ Integer socket = mStreams.remove(stream);
+ if (socket != null) {
+ remove(socket);
}
}
- private native void remove(int id);
+ private native void remove(int socket);
/**
* Sends a DTMF digit to every {@link AudioStream} in this group. Currently
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index fc1ed9b..08a8d1c 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -367,7 +367,7 @@
MSG_TRUNC | MSG_DONTWAIT);
// Do we need to check SSRC, sequence, and timestamp? They are not
- // reliable but at least they can be used to identity duplicates?
+ // reliable but at least they can be used to identify duplicates?
if (length < 12 || length > (int)sizeof(buffer) ||
(ntohl(*(uint32_t *)buffer) & 0xC07F0000) != mCodecMagic) {
LOGD("stream[%d] malformed packet", mSocket);
@@ -526,70 +526,6 @@
LOGD("group[%d] is dead", mDeviceSocket);
}
-#define FROYO_COMPATIBLE
-#ifdef FROYO_COMPATIBLE
-
-// Copied from AudioRecord.cpp.
-status_t AudioRecord_getMinFrameCount(
- int* frameCount,
- uint32_t sampleRate,
- int format,
- int channelCount)
-{
- size_t size = 0;
- if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size)
- != NO_ERROR) {
- LOGE("AudioSystem could not query the input buffer size.");
- return NO_INIT;
- }
-
- if (size == 0) {
- LOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d",
- sampleRate, format, channelCount);
- return BAD_VALUE;
- }
-
- // We double the size of input buffer for ping pong use of record buffer.
- size <<= 1;
-
- if (AudioSystem::isLinearPCM(format)) {
- size /= channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
- }
-
- *frameCount = size;
- return NO_ERROR;
-}
-
-// Copied from AudioTrack.cpp.
-status_t AudioTrack_getMinFrameCount(
- int* frameCount,
- int streamType,
- uint32_t sampleRate)
-{
- int afSampleRate;
- if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
- return NO_INIT;
- }
- int afFrameCount;
- if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
- return NO_INIT;
- }
- uint32_t afLatency;
- if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
- return NO_INIT;
- }
-
- // Ensure that buffer depth covers at least audio hardware latency
- uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);
- if (minBufCount < 2) minBufCount = 2;
-
- *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :
- afFrameCount * minBufCount * sampleRate / afSampleRate;
- return NO_ERROR;
-}
-
-#endif
-
bool AudioGroup::set(int sampleRate, int sampleCount)
{
mEventQueue = epoll_create(2);
@@ -603,15 +539,6 @@
// Find out the frame count for AudioTrack and AudioRecord.
int output = 0;
int input = 0;
-#ifdef FROYO_COMPATIBLE
- if (AudioTrack_getMinFrameCount(&output, AudioSystem::VOICE_CALL,
- sampleRate) != NO_ERROR || output <= 0 ||
- AudioRecord_getMinFrameCount(&input, sampleRate,
- AudioSystem::PCM_16_BIT, 1) != NO_ERROR || input <= 0) {
- LOGE("cannot compute frame count");
- return false;
- }
-#else
if (AudioTrack::getMinFrameCount(&output, AudioSystem::VOICE_CALL,
sampleRate) != NO_ERROR || output <= 0 ||
AudioRecord::getMinFrameCount(&input, sampleRate,
@@ -619,7 +546,6 @@
LOGE("cannot compute frame count");
return false;
}
-#endif
LOGD("reported frame count: output %d, input %d", output, input);
output = (output + sampleCount - 1) / sampleCount * sampleCount;
@@ -771,6 +697,10 @@
for (AudioStream *stream = mChain; stream->mNext; stream = stream->mNext) {
AudioStream *target = stream->mNext;
if (target->mSocket == socket) {
+ if (epoll_ctl(mEventQueue, EPOLL_CTL_DEL, socket, NULL)) {
+ LOGE("epoll_ctl: %s", strerror(errno));
+ return false;
+ }
stream->mNext = target->mNext;
LOGD("stream[%d] leaves group[%d]", socket, mDeviceSocket);
delete target;
@@ -874,7 +804,7 @@
static jfieldID gNative;
static jfieldID gMode;
-jint add(JNIEnv *env, jobject thiz, jint mode,
+void add(JNIEnv *env, jobject thiz, jint mode,
jint socket, jstring jRemoteAddress, jint remotePort,
jstring jCodecName, jint sampleRate, jint sampleCount,
jint codecType, jint dtmfType)
@@ -887,7 +817,7 @@
sockaddr_storage remote;
if (parse(env, jRemoteAddress, remotePort, &remote) < 0) {
// Exception already thrown.
- return -1;
+ goto error;
}
if (sampleRate < 0 || sampleCount < 0 || codecType < 0 || codecType > 127) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
@@ -895,12 +825,12 @@
}
if (!jCodecName) {
jniThrowNullPointerException(env, "codecName");
- return -1;
+ goto error;
}
codecName = env->GetStringUTFChars(jCodecName, NULL);
if (!codecName) {
// Exception already thrown.
- return -1;
+ goto error;
}
// Create audio stream.
@@ -909,8 +839,10 @@
codecType, dtmfType)) {
jniThrowException(env, "java/lang/IllegalStateException",
"cannot initialize audio stream");
+ env->ReleaseStringUTFChars(jCodecName, codecName);
goto error;
}
+ env->ReleaseStringUTFChars(jCodecName, codecName);
socket = -1;
// Create audio group.
@@ -934,16 +866,13 @@
// Succeed.
env->SetIntField(thiz, gNative, (int)group);
- env->ReleaseStringUTFChars(jCodecName, codecName);
- return socket;
+ return;
error:
delete group;
delete stream;
close(socket);
env->SetIntField(thiz, gNative, NULL);
- env->ReleaseStringUTFChars(jCodecName, codecName);
- return -1;
}
void remove(JNIEnv *env, jobject thiz, jint socket)
@@ -976,7 +905,7 @@
}
JNINativeMethod gMethods[] = {
- {"add", "(IILjava/lang/String;ILjava/lang/String;IIII)I", (void *)add},
+ {"add", "(IILjava/lang/String;ILjava/lang/String;IIII)V", (void *)add},
{"remove", "(I)V", (void *)remove},
{"setMode", "(I)V", (void *)setMode},
{"sendDtmf", "(I)V", (void *)sendDtmf},