diff options
57 files changed, 803 insertions, 755 deletions
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 @@ public final class ActivityThread { 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 @@ class ContextImpl extends Context { boolean returnValue; boolean hasListeners; + boolean changesMade = false; List<String> keysModified = null; Set<OnSharedPreferenceChangeListener> listeners = null; @@ -2857,17 +2858,31 @@ class ContextImpl extends Context { 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 @@ class ContextImpl extends Context { mModified.clear(); } - returnValue = writeFileLocked(); + returnValue = writeFileLocked(changesMade); } if (hasListeners) { @@ -2923,9 +2938,16 @@ class ContextImpl extends Context { 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 @@ public interface IActivityManager extends IInterface { /** 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 @@ public interface IActivityManager extends IInterface { 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 @@ public abstract class ContentProvider implements ComponentCallbacks { private String mReadPermission; private String mWritePermission; private PathPermission[] mPathPermissions; + private boolean mExported; private Transport mTransport = new Transport(); @@ -257,9 +258,9 @@ public abstract class ContentProvider implements ComponentCallbacks { 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 @@ public abstract class ContentProvider implements ComponentCallbacks { 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 @@ public abstract class ContentProvider implements ComponentCallbacks { setReadPermission(info.readPermission); setWritePermission(info.writePermission); setPathPermissions(info.pathPermissions); + mExported = info.exported; } ContentProvider.this.onCreate(); } diff --git a/core/java/android/content/res/ObbInfo.java b/core/java/android/content/res/ObbInfo.java index b18d784..838c5ff 100644 --- a/core/java/android/content/res/ObbInfo.java +++ b/core/java/android/content/res/ObbInfo.java @@ -25,6 +25,9 @@ import android.os.Parcelable; * @hide */ public class ObbInfo implements Parcelable { + /** Flag noting that this OBB is an overlay patch for a base OBB. */ + public static final int OBB_OVERLAY = 1 << 0; + /** * The name of the package to which the OBB file belongs. */ @@ -35,13 +38,26 @@ public class ObbInfo implements Parcelable { */ public int version; + /** + * The flags relating to the OBB. + */ + public int flags; + public ObbInfo() { } public String toString() { - return "ObbInfo{" - + Integer.toHexString(System.identityHashCode(this)) - + " packageName=" + packageName + ",version=" + version + "}"; + StringBuilder sb = new StringBuilder(); + sb.append("ObbInfo{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" packageName="); + sb.append(packageName); + sb.append(",version="); + sb.append(version); + sb.append(",flags="); + sb.append(flags); + sb.append('}'); + return sb.toString(); } public int describeContents() { @@ -51,6 +67,7 @@ public class ObbInfo implements Parcelable { public void writeToParcel(Parcel dest, int parcelableFlags) { dest.writeString(packageName); dest.writeInt(version); + dest.writeInt(flags); } public static final Parcelable.Creator<ObbInfo> CREATOR @@ -67,5 +84,6 @@ public class ObbInfo implements Parcelable { private ObbInfo(Parcel source) { packageName = source.readString(); version = source.readInt(); + flags = source.readInt(); } } 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 @@ public class SensorManager * 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 @@ public class MobileDataStateTracker extends NetworkStateTracker { 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 @@ public class MobileDataStateTracker extends NetworkStateTracker { } 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 @@ public class MobileDataStateTracker extends NetworkStateTracker { } 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 @@ public class MobileDataStateTracker extends NetworkStateTracker { } 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/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index cb1794f..df0b69c 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -304,6 +304,8 @@ public class StorageManager * file matches a package ID that is owned by the calling program's UID. * That is, shared UID applications can obtain access to any other * application's OBB that shares its UID. + * <p> + * STOPSHIP document more; discuss lack of guarantees of security * * @param filename the path to the OBB file * @param key decryption key @@ -328,6 +330,8 @@ public class StorageManager * file matches a package ID that is owned by the calling program's UID. * That is, shared UID applications can obtain access to any other * application's OBB that shares its UID. + * <p> + * STOPSHIP document more; discuss lack of guarantees of security * * @param filename path to the OBB file * @param force whether to kill any programs using this in order to unmount 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 @@ public class ViewDebug { } }) : 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 abstract class WindowOrientationListener { } } - 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 @@ public abstract class WindowOrientationListener { 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 @@ public abstract class WindowOrientationListener { 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 @@ public abstract class WindowOrientationListener { 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 @@ public abstract class WindowOrientationListener { 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 @@ public abstract class WindowOrientationListener { * 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 @@ public abstract class WindowOrientationListener { } else if (mTiltDistrust > 0) { mTiltDistrust--; } - return fullyTilted; } /** @@ -389,8 +397,8 @@ public abstract class WindowOrientationListener { */ 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 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, /////////////////////////////////////////////////////////////////////////////// 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 @@ public: virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable); private: - JNIEnv* fEnv; + JavaVM* fVM; bool fReportSizeToVM; }; @@ -92,7 +92,7 @@ public: virtual bool reportMemory(size_t memorySize); private: - JNIEnv* fEnv; + JavaVM* fVM; size_t fTotalSize; }; diff --git a/core/jni/android_content_res_ObbScanner.cpp b/core/jni/android_content_res_ObbScanner.cpp index 1239274..62c89fc 100644 --- a/core/jni/android_content_res_ObbScanner.cpp +++ b/core/jni/android_content_res_ObbScanner.cpp @@ -31,6 +31,7 @@ static struct { jfieldID packageName; jfieldID version; + jfieldID flags; } gObbInfoClassInfo; static jboolean android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject clazz, jstring file, @@ -85,6 +86,8 @@ int register_android_content_res_ObbScanner(JNIEnv* env) "packageName", "Ljava/lang/String;"); GET_FIELD_ID(gObbInfoClassInfo.version, gObbInfoClassInfo.clazz, "version", "I"); + GET_FIELD_ID(gObbInfoClassInfo.flags, gObbInfoClassInfo.clazz, + "flags", "I"); return AndroidRuntime::registerNativeMethods(env, "android/content/res/ObbScanner", gMethods, NELEM(gMethods)); diff --git a/media/libstagefright/mpeg2ts/ABitReader.h b/include/media/stagefright/foundation/ABitReader.h index 5135211..5135211 100644 --- a/media/libstagefright/mpeg2ts/ABitReader.h +++ b/include/media/stagefright/foundation/ABitReader.h 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 @@ public: 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 @@ private: // 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 @@ private: 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 @@ private: inline void clear() { fields = 0; } - - inline bool isDirty() { - return fields != 0; - } } mAccumulator; float mXScale; @@ -702,7 +698,7 @@ private: } historyData[AVERAGING_HISTORY_SIZE]; } mAveragingTouchFilter; - struct JumpTouchFilterState { + struct JumpyTouchFilterState { uint32_t jumpyPointsDropped; } mJumpyTouchFilter; @@ -765,10 +761,6 @@ private: inline void clear() { fields = 0; } - - inline bool isDirty() { - return fields != 0; - } } mAccumulator; bool mDown; @@ -804,7 +796,8 @@ private: 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 @@ private: int32_t absMTWidthMinor; int32_t absMTOrientation; int32_t absMTTrackingId; + int32_t absMTPressure; inline void clear() { fields = 0; @@ -829,10 +823,6 @@ private: pointerCount = 0; pointers[0].clear(); } - - inline bool isDirty() { - return pointerCount != 0; - } } mAccumulator; void initialize(); diff --git a/include/utils/ObbFile.h b/include/utils/ObbFile.h index d2ca82e..5243f50 100644 --- a/include/utils/ObbFile.h +++ b/include/utils/ObbFile.h @@ -18,12 +18,16 @@ #define OBBFILE_H_ #include <stdint.h> +#include <strings.h> #include <utils/RefBase.h> #include <utils/String8.h> namespace android { +// OBB flags (bit 0) +#define OBB_OVERLAY (1 << 0) + class ObbFile : public RefBase { protected: virtual ~ObbFile(); @@ -46,18 +50,38 @@ public: return mPackageName; } - int32_t getVersion() const { - return mVersion; - } - void setPackageName(String8 packageName) { mPackageName = packageName; } + int32_t getVersion() const { + return mVersion; + } + void setVersion(int32_t version) { mVersion = version; } + int32_t getFlags() const { + return mFlags; + } + + void setFlags(int32_t flags) { + mFlags = flags; + } + + bool isOverlay() { + return (mFlags & OBB_OVERLAY) == OBB_OVERLAY; + } + + void setOverlay(bool overlay) { + if (overlay) { + mFlags |= OBB_OVERLAY; + } else { + mFlags &= ~OBB_OVERLAY; + } + } + static inline uint32_t get4LE(const unsigned char* buf) { return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } @@ -76,6 +100,9 @@ private: /* Package version this ObbFile is associated with */ int32_t mVersion; + /* Flags for this OBB type. */ + int32_t mFlags; + const char* mFileName; size_t mFileSize; diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index a3c34d0..891661d 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -581,7 +581,6 @@ int EventHub::open_device(const char *deviceName) if (strcmp(name, test) == 0) { LOGI("ignoring event id %s driver %s\n", deviceName, test); close(fd); - fd = -1; return -1; } } @@ -813,6 +812,14 @@ int EventHub::open_device(const char *deviceName) 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 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic 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 @@ void InputDispatcher::dispatchOnce() { } } 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 @@ void InputDispatcher::dispatchOnce() { mInboundQueue.dequeue(entry); mAllocator.releaseEventEntry(entry); skipPoll = true; + + Throttle: ; } } @@ -192,8 +254,8 @@ void InputDispatcher::dispatchOnce() { 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 @@ void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry, 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 @@ void TrackballInputMapper::reset() { mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE; mAccumulator.btnMouse = false; sync(when); - mAccumulator.clear(); } InputMapper::reset(); @@ -958,9 +957,9 @@ void TrackballInputMapper::process(const RawEvent* rawEvent) { 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 @@ void TrackballInputMapper::process(const RawEvent* rawEvent) { 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::process(const RawEvent* rawEvent) { } 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 @@ void TrackballInputMapper::sync(nsecs_t when) { } // release lock applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime); + + mAccumulator.clear(); } void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction, @@ -2380,8 +2382,8 @@ void SingleTouchInputMapper::initialize() { 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 @@ void SingleTouchInputMapper::process(const RawEvent* rawEvent) { 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 @@ void SingleTouchInputMapper::process(const RawEvent* rawEvent) { 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::process(const RawEvent* rawEvent) { } 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 @@ void SingleTouchInputMapper::sync(nsecs_t when) { 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 @@ void SingleTouchInputMapper::sync(nsecs_t when) { } syncTouch(when, true); + + mAccumulator.clear(); } void SingleTouchInputMapper::configureAxes() { @@ -2494,8 +2496,8 @@ void SingleTouchInputMapper::configureAxes() { 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 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) { } case SYN_REPORT: - if (mAccumulator.isDirty()) { - sync(rawEvent->when); - mAccumulator.clear(); - } + sync(rawEvent->when); break; } break; @@ -2598,11 +2597,7 @@ void MultiTouchInputMapper::process(const RawEvent* rawEvent) { 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 @@ void MultiTouchInputMapper::sync(nsecs_t when) { 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); + // Some drivers send empty MT sync packets without X / Y to indicate a pointer up. + // Drop this finger. continue; -#endif } - if (mAccumulator.pointers[inIndex].absMTTouchMajor <= 0) { - // Pointer is not down. Drop it. - continue; + PointerData& outPointer = mCurrentTouch.pointers[outCount]; + outPointer.x = inPointer.absMTPositionX; + outPointer.y = inPointer.absMTPositionY; + + 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].x = mAccumulator.pointers[inIndex].absMTPositionX; - mCurrentTouch.pointers[outCount].y = mAccumulator.pointers[inIndex].absMTPositionY; + if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) { + outPointer.touchMinor = inPointer.absMTTouchMinor; + } else { + outPointer.touchMinor = outPointer.touchMajor; + } + + if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) { + outPointer.toolMajor = inPointer.absMTWidthMajor; + } else { + outPointer.toolMajor = outPointer.touchMajor; + } - 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_WIDTH_MINOR) { + outPointer.toolMinor = inPointer.absMTWidthMinor; + } else { + outPointer.toolMinor = outPointer.toolMajor; + } - 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_ORIENTATION) { + outPointer.orientation = inPointer.absMTOrientation; + } else { + outPointer.orientation = 0; + } - mCurrentTouch.pointers[outCount].orientation = - (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) != 0 - ? mAccumulator.pointers[inIndex].absMTOrientation : 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; + } - // 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; + // 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 @@ void MultiTouchInputMapper::sync(nsecs_t when) { havePointerIds = false; } else { - mCurrentTouch.pointers[outCount].id = id; + outPointer.id = id; mCurrentTouch.idToIndex[id] = outCount; mCurrentTouch.idBits.markBit(id); } @@ -2683,6 +2701,8 @@ void MultiTouchInputMapper::sync(nsecs_t when) { mCurrentTouch.pointerCount = outCount; syncTouch(when, havePointerIds); + + mAccumulator.clear(); } void MultiTouchInputMapper::configureAxes() { @@ -2697,6 +2717,7 @@ void MultiTouchInputMapper::configureAxes() { 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 @@ void MultiTouchInputMapper::configureAxes() { mAxes.toolMinor = mAxes.toolMajor; } - mAxes.pressure = mAxes.touchMajor; + if (! mAxes.pressure.valid) { + mAxes.pressure = mAxes.touchMajor; + } + mAxes.size = mAxes.toolMajor; } diff --git a/libs/utils/ObbFile.cpp b/libs/utils/ObbFile.cpp index adedf0c..e170ab8 100644 --- a/libs/utils/ObbFile.cpp +++ b/libs/utils/ObbFile.cpp @@ -29,12 +29,13 @@ #define kFooterTagSize 8 /* last two 32-bit integers */ -#define kFooterMinSize 21 /* 32-bit signature version - * 32-bit package version - * 32-bit package name size - * 1-character package name - * 32-bit footer size - * 32-bit footer marker +#define kFooterMinSize 25 /* 32-bit signature version (4 bytes) + * 32-bit package version (4 bytes) + * 32-bit flags (4 bytes) + * 32-bit package name size (4-bytes) + * >=1-character package name (1 byte) + * 32-bit footer size (4 bytes) + * 32-bit footer marker (4 bytes) */ #define kMaxBufSize 32768 /* Maximum file read buffer */ @@ -45,8 +46,9 @@ /* offsets in version 1 of the header */ #define kPackageVersionOffset 4 -#define kPackageNameLenOffset 8 -#define kPackageNameOffset 12 +#define kFlagsOffset 8 +#define kPackageNameLenOffset 12 +#define kPackageNameOffset 16 /* * TEMP_FAILURE_RETRY is defined by some, but not all, versions of @@ -78,7 +80,10 @@ typedef off64_t my_off64_t; namespace android { ObbFile::ObbFile() : - mVersion(-1) { + mPackageName(""), + mVersion(-1), + mFlags(0) +{ } ObbFile::~ObbFile() { @@ -199,6 +204,7 @@ bool ObbFile::parseObbFile(int fd) } mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset); + mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset); uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset); if (packageNameLen <= 0 @@ -268,6 +274,12 @@ bool ObbFile::writeTo(int fd) return false; } + put4LE(intBuf, mFlags); + if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { + LOGW("couldn't write package version"); + return false; + } + size_t packageNameLen = mPackageName.size(); put4LE(intBuf, packageNameLen); if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { @@ -280,7 +292,7 @@ bool ObbFile::writeTo(int fd) return false; } - put4LE(intBuf, 3*sizeof(uint32_t) + packageNameLen); + put4LE(intBuf, kPackageNameOffset + packageNameLen); if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) { LOGW("couldn't write footer size: %s", strerror(errno)); return false; diff --git a/media/java/android/media/BassBoost.java b/media/java/android/media/BassBoost.java index 73c1751..476b056 100644 --- a/media/java/android/media/BassBoost.java +++ b/media/java/android/media/BassBoost.java @@ -99,7 +99,7 @@ public class BassBoost extends AudioEffect { UnsupportedOperationException, RuntimeException { super(EFFECT_TYPE_BASS_BOOST, EFFECT_TYPE_NULL, priority, audioSession); - short[] value = new short[1]; + int[] value = new int[1]; checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value)); mStrengthSupported = (value[0] != 0); } diff --git a/media/java/android/media/Virtualizer.java b/media/java/android/media/Virtualizer.java index d03c2a8..b08f36e 100644 --- a/media/java/android/media/Virtualizer.java +++ b/media/java/android/media/Virtualizer.java @@ -100,7 +100,7 @@ public class Virtualizer extends AudioEffect { UnsupportedOperationException, RuntimeException { super(EFFECT_TYPE_VIRTUALIZER, EFFECT_TYPE_NULL, priority, audioSession); - short[] value = new short[1]; + int[] value = new int[1]; checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value)); mStrengthSupported = (value[0] != 0); } diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index a70bdff..bcd646a 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -1626,9 +1626,15 @@ int BassBoost_getParameter(EffectContext *pContext, switch (param){ case BASSBOOST_PARAM_STRENGTH_SUPPORTED: + if (*pValueSize != sizeof(uint32_t)){ + LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize %d", *pValueSize); + return -EINVAL; + } + *pValueSize = sizeof(uint32_t); + break; case BASSBOOST_PARAM_STRENGTH: if (*pValueSize != sizeof(int16_t)){ - LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize2 %d", *pValueSize); + LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize %d", *pValueSize); return -EINVAL; } *pValueSize = sizeof(int16_t); @@ -1736,9 +1742,16 @@ int Virtualizer_getParameter(EffectContext *pContext, switch (param){ case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: + if (*pValueSize != sizeof(uint32_t)){ + LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize); + return -EINVAL; + } + *pValueSize = sizeof(uint32_t); + break; + case VIRTUALIZER_PARAM_STRENGTH: if (*pValueSize != sizeof(int16_t)){ - LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize2 %d",*pValueSize); + LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize); return -EINVAL; } *pValueSize = sizeof(int16_t); diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index b8b2f3f..86fa668 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -39,6 +39,7 @@ LOCAL_SRC_FILES:= \ TimedEventQueue.cpp \ Utils.cpp \ WAVExtractor.cpp \ + avc_utils.cpp \ string.cpp LOCAL_C_INCLUDES:= \ diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp new file mode 100644 index 0000000..511ae12 --- /dev/null +++ b/media/libstagefright/avc_utils.cpp @@ -0,0 +1,91 @@ +/* + * 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 "include/avc_utils.h" + +#include <media/stagefright/foundation/ABitReader.h> +#include <media/stagefright/foundation/ADebug.h> + +namespace android { + +static unsigned parseUE(ABitReader *br) { + unsigned numZeroes = 0; + while (br->getBits(1) == 0) { + ++numZeroes; + } + + unsigned x = br->getBits(numZeroes); + + return x + (1u << numZeroes) - 1; +} + +// Determine video dimensions from the sequence parameterset. +void FindAVCDimensions( + const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height) { + ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1); + + unsigned profile_idc = br.getBits(8); + br.skipBits(16); + parseUE(&br); // seq_parameter_set_id + + if (profile_idc == 100 || profile_idc == 110 + || profile_idc == 122 || profile_idc == 244 + || profile_idc == 44 || profile_idc == 83 || profile_idc == 86) { + unsigned chroma_format_idc = parseUE(&br); + if (chroma_format_idc == 3) { + br.skipBits(1); // residual_colour_transform_flag + } + parseUE(&br); // bit_depth_luma_minus8 + parseUE(&br); // bit_depth_chroma_minus8 + br.skipBits(1); // qpprime_y_zero_transform_bypass_flag + CHECK_EQ(br.getBits(1), 0u); // seq_scaling_matrix_present_flag + } + + parseUE(&br); // log2_max_frame_num_minus4 + unsigned pic_order_cnt_type = parseUE(&br); + + if (pic_order_cnt_type == 0) { + parseUE(&br); // log2_max_pic_order_cnt_lsb_minus4 + } else if (pic_order_cnt_type == 1) { + // offset_for_non_ref_pic, offset_for_top_to_bottom_field and + // offset_for_ref_frame are technically se(v), but since we are + // just skipping over them the midpoint does not matter. + + br.getBits(1); // delta_pic_order_always_zero_flag + parseUE(&br); // offset_for_non_ref_pic + parseUE(&br); // offset_for_top_to_bottom_field + + unsigned num_ref_frames_in_pic_order_cnt_cycle = parseUE(&br); + for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) { + parseUE(&br); // offset_for_ref_frame + } + } + + parseUE(&br); // num_ref_frames + br.getBits(1); // gaps_in_frame_num_value_allowed_flag + + unsigned pic_width_in_mbs_minus1 = parseUE(&br); + unsigned pic_height_in_map_units_minus1 = parseUE(&br); + unsigned frame_mbs_only_flag = br.getBits(1); + + *width = pic_width_in_mbs_minus1 * 16 + 16; + + *height = (2 - frame_mbs_only_flag) + * (pic_height_in_map_units_minus1 * 16 + 16); +} + +} // namespace android + diff --git a/media/libstagefright/mpeg2ts/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp index 24c8df8..24c8df8 100644 --- a/media/libstagefright/mpeg2ts/ABitReader.cpp +++ b/media/libstagefright/foundation/ABitReader.cpp diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk index 35eea7e..f6a8a52 100644 --- a/media/libstagefright/foundation/Android.mk +++ b/media/libstagefright/foundation/Android.mk @@ -3,6 +3,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ AAtomizer.cpp \ + ABitReader.cpp \ ABuffer.cpp \ ADebug.cpp \ AHandler.cpp \ diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h new file mode 100644 index 0000000..cc405b5 --- /dev/null +++ b/media/libstagefright/include/avc_utils.h @@ -0,0 +1,30 @@ +/* + * 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 AVC_UTILS_H_ + +#define AVC_UTILS_H_ + +#include <media/stagefright/foundation/ABuffer.h> + +namespace android { + +void FindAVCDimensions( + const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height); + +} // namespace android + +#endif // AVC_UTILS_H_ diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index d05975d..26a0fb3 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -16,9 +16,10 @@ #include "ATSParser.h" -#include "ABitReader.h" #include "AnotherPacketSource.h" +#include "include/avc_utils.h" +#include <media/stagefright/foundation/ABitReader.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> @@ -473,60 +474,6 @@ static sp<ABuffer> FindNAL( } } -static unsigned parseUE(ABitReader *br) { - unsigned numZeroes = 0; - while (br->getBits(1) == 0) { - ++numZeroes; - } - - unsigned x = br->getBits(numZeroes); - - return x + (1u << numZeroes) - 1; -} - -// Determine video dimensions from the sequence parameterset. -static void FindDimensions( - const sp<ABuffer> seqParamSet, int32_t *width, int32_t *height) { - ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1); - - unsigned profile_idc = br.getBits(8); - br.skipBits(16); - parseUE(&br); // seq_parameter_set_id - - if (profile_idc == 100 || profile_idc == 110 - || profile_idc == 122 || profile_idc == 144) { - TRESPASS(); - } - - parseUE(&br); // log2_max_frame_num_minus4 - unsigned pic_order_cnt_type = parseUE(&br); - - if (pic_order_cnt_type == 0) { - parseUE(&br); // log2_max_pic_order_cnt_lsb_minus4 - } else if (pic_order_cnt_type == 1) { - br.getBits(1); // delta_pic_order_always_zero_flag - parseUE(&br); // offset_for_non_ref_pic - parseUE(&br); // offset_for_top_to_bottom_field - - unsigned num_ref_frames_in_pic_order_cnt_cycle = parseUE(&br); - for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) { - parseUE(&br); // offset_for_ref_frame - } - } - - parseUE(&br); // num_ref_frames - br.getBits(1); // gaps_in_frame_num_value_allowed_flag - - unsigned pic_width_in_mbs_minus1 = parseUE(&br); - unsigned pic_height_in_map_units_minus1 = parseUE(&br); - unsigned frame_mbs_only_flag = br.getBits(1); - - *width = pic_width_in_mbs_minus1 * 16 + 16; - - *height = (2 - frame_mbs_only_flag) - * (pic_height_in_map_units_minus1 * 16 + 16); -} - static sp<ABuffer> MakeAVCCodecSpecificData( const sp<ABuffer> &buffer, int32_t *width, int32_t *height) { const uint8_t *data = buffer->data(); @@ -537,7 +484,7 @@ static sp<ABuffer> MakeAVCCodecSpecificData( return NULL; } - FindDimensions(seqParamSet, width, height); + FindAVCDimensions(seqParamSet, width, height); size_t stopOffset; sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset); diff --git a/media/libstagefright/mpeg2ts/Android.mk b/media/libstagefright/mpeg2ts/Android.mk index b6772eb..3544b4c 100644 --- a/media/libstagefright/mpeg2ts/Android.mk +++ b/media/libstagefright/mpeg2ts/Android.mk @@ -3,7 +3,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - ABitReader.cpp \ AnotherPacketSource.cpp \ ATSParser.cpp \ MPEG2TSExtractor.cpp \ diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp index 224b4bf..353c746 100644 --- a/media/libstagefright/rtsp/APacketSource.cpp +++ b/media/libstagefright/rtsp/APacketSource.cpp @@ -18,6 +18,10 @@ #include "ASessionDescription.h" +#include "avc_utils.h" + +#include <ctype.h> + #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> @@ -37,6 +41,10 @@ static bool GetAttribute(const char *s, const char *key, AString *value) { size_t keyLen = strlen(key); for (;;) { + while (isspace(*s)) { + ++s; + } + const char *colonPos = strchr(s, ';'); size_t len = @@ -90,7 +98,11 @@ static sp<ABuffer> decodeHex(const AString &s) { return buffer; } -static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) { +static sp<ABuffer> MakeAVCCodecSpecificData( + const char *params, int32_t *width, int32_t *height) { + *width = 0; + *height = 0; + AString val; if (!GetAttribute(params, "profile-level-id", &val)) { return NULL; @@ -172,6 +184,11 @@ static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) { memcpy(out, nal->data(), nal->size()); out += nal->size(); + + if (i == 0) { + FindAVCDimensions(nal, width, height); + LOG(INFO) << "dimensions " << *width << "x" << *height; + } } *out++ = numPicParameterSets; @@ -187,7 +204,7 @@ static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) { out += nal->size(); } - hexdump(csd->data(), csd->size()); + // hexdump(csd->data(), csd->size()); return csd; } @@ -224,7 +241,7 @@ sp<ABuffer> MakeAACCodecSpecificData(const char *params) { csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff; csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff; - hexdump(csd->data(), csd->size()); + // hexdump(csd->data(), csd->size()); return csd; } @@ -253,25 +270,42 @@ APacketSource::APacketSource( mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); int32_t width, height; - sessionDesc->getDimensions(index, PT, &width, &height); - - mFormat->setInt32(kKeyWidth, width); - mFormat->setInt32(kKeyHeight, height); + if (!sessionDesc->getDimensions(index, PT, &width, &height)) { + width = -1; + height = -1; + } + int32_t encWidth, encHeight; sp<ABuffer> codecSpecificData = - MakeAVCCodecSpecificData(params.c_str()); + MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight); if (codecSpecificData != NULL) { + if (width < 0) { + // If no explicit width/height given in the sdp, use the dimensions + // extracted from the first sequence parameter set. + width = encWidth; + height = encHeight; + } + mFormat->setData( kKeyAVCC, 0, codecSpecificData->data(), codecSpecificData->size()); + } else if (width < 0) { + mInitCheck = ERROR_UNSUPPORTED; + return; } + + mFormat->setInt32(kKeyWidth, width); + mFormat->setInt32(kKeyHeight, height); } else if (!strncmp(desc.c_str(), "H263-2000/", 10) || !strncmp(desc.c_str(), "H263-1998/", 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 @@ bool ARTSPConnection::ParseURL( 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 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) { 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 @@ void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) { mSocket = -1; flushPendingRequests(); - } + } sp<AMessage> reply; CHECK(msg->findMessage("reply", &reply)); @@ -347,7 +358,13 @@ void ARTSPConnection::onReceiveResponse() { 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::getFormatType( } } -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 @@ void ASessionDescription::getDimensions( *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 @@ struct ASessionDescription : public RefBase { 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 @@ struct MyHandler : public AHandler { 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 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers() 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 @@ bool AudioFlinger::MixerThread::threadLoop() } if (mSuspended) { - sleepTime = idleSleepTime; + sleepTime = suspendSleepTimeUs(); } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { @@ -2021,6 +2021,11 @@ uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() 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 @@ bool AudioFlinger::DirectOutputThread::threadLoop() } if (mSuspended) { - sleepTime = idleSleepTime; + sleepTime = suspendSleepTimeUs(); } // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { @@ -2486,6 +2491,18 @@ uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() 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 @@ bool AudioFlinger::DuplicatingThread::threadLoop() } 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 @@ private: 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 @@ private: virtual void deleteTrackName_l(int name); virtual uint32_t activeSleepTimeUs(); virtual uint32_t idleSleepTimeUs(); + virtual uint32_t suspendSleepTimeUs(); AudioMixer* mAudioMixer; }; @@ -744,6 +746,7 @@ private: 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.content.res.Configuration; 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 @@ import java.util.ArrayList; /* * 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 @@ public class InputManager { 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return false; } } + if (!pi.exported && pi.applicationInfo.uid != uid) { + return false; + } return true; } catch (RemoteException e) { return false; @@ -4199,8 +4202,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ public final class ActivityManagerService extends ActivityManagerNative implemen 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 @@ static struct { jmethodID filterJumpyTouchEvents; jmethodID getVirtualKeyDefinitions; jmethodID getExcludedDeviceNames; + jmethodID getMaxEventsPerSecond; } gCallbacksClassInfo; static struct { @@ -249,6 +250,7 @@ public: 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 @@ private: 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 @@ private: 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 @@ nsecs_t NativeInputManager::getKeyRepeatTimeout() { } } +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 @@ int register_android_server_InputManager(JNIEnv* env) { 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 @@ LOCAL_SRC_FILES:= \ 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 @@ DisplayHardware::DisplayHardware( const sp<SurfaceFlinger>& flinger, uint32_t dpy) : DisplayHardwareBase(flinger, dpy), - mFlags(0), mHwc(0) + mFlags(0) { init(dpy); } @@ -262,17 +262,6 @@ void DisplayHardware::init(uint32_t dpy) // 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 @@ void DisplayHardware::flip(const Region& dirty) const } 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 @@ public: 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 @@ private: 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 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, 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 @@ public: 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::drawRegion(const Region& reg) const } } -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 @@ public: 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 @@ SurfaceFlinger::SurfaceFlinger() mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"), mDump("android.permission.DUMP"), mVisibleRegionsDirty(false), - mHwWorkListDirty(false), mDeferReleaseConsole(false), mFreezeDisplay(false), mFreezeCount(0), @@ -370,11 +368,6 @@ bool SurfaceFlinger::threadLoop() // 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 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) handleTransactionLocked(transactionFlags, ditchedLayers); mLastTransactionTime = systemTime() - now; mDebugInTransaction = 0; - mHwWorkListDirty = true; // here the transaction has been committed } @@ -458,7 +450,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) * 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::commitTransaction() 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 @@ void SurfaceFlinger::handlePageFlip() mWormholeRegion = screenRegion.subtract(opaqueRegion); mVisibleRegionsDirty = false; - mHwWorkListDirty = true; } unlockPageFlip(currentLayers); @@ -747,20 +737,6 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) } } -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 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) // 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 @@ private: 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 @@ private: Region mInvalidRegion; Region mWormholeRegion; bool mVisibleRegionsDirty; - bool mHwWorkListDirty; bool mDeferReleaseConsole; bool mFreezeDisplay; int32_t mFreezeCount; diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp index 2a9bf04..49e077f 100644 --- a/tools/obbtool/Main.cpp +++ b/tools/obbtool/Main.cpp @@ -29,7 +29,7 @@ static const char* gProgVersion = "1.0"; static int wantUsage = 0; static int wantVersion = 0; -#define ADD_OPTS "n:v:f:c:" +#define ADD_OPTS "n:v:o" static const struct option longopts[] = { {"help", no_argument, &wantUsage, 1}, {"version", no_argument, &wantVersion, 1}, @@ -37,8 +37,7 @@ static const struct option longopts[] = { /* Args for "add" */ {"name", required_argument, NULL, 'n'}, {"version", required_argument, NULL, 'v'}, - {"filesystem", required_argument, NULL, 'f'}, - {"crypto", required_argument, NULL, 'c'}, + {"overlay", optional_argument, NULL, 'o'}, {NULL, 0, NULL, '\0'} }; @@ -46,8 +45,7 @@ static const struct option longopts[] = { struct package_info_t { char* packageName; int packageVersion; - char* filesystem; - char* crypto; + bool overlay; }; /* @@ -77,6 +75,7 @@ void doAdd(const char* filename, struct package_info_t* info) { obb->setPackageName(String8(info->packageName)); obb->setVersion(info->packageVersion); + obb->setOverlay(info->overlay); if (!obb->writeTo(filename)) { fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n", @@ -112,6 +111,8 @@ void doInfo(const char* filename) { printf("OBB info for '%s':\n", filename); printf("Package name: %s\n", obb->getPackageName().string()); printf(" Version: %d\n", obb->getVersion()); + printf(" Flags: 0x%08x\n", obb->getFlags()); + printf(" Overlay: %s\n", obb->isOverlay() ? "true" : "false"); } /* @@ -143,7 +144,7 @@ int main(int argc, char* const argv[]) case 'n': package_info.packageName = optarg; break; - case 'v': + case 'v': { char *end; package_info.packageVersion = strtol(optarg, &end, 10); if (*optarg == '\0' || *end != '\0') { @@ -152,11 +153,9 @@ int main(int argc, char* const argv[]) goto bail; } break; - case 'f': - package_info.filesystem = optarg; - break; - case 'c': - package_info.crypto = optarg; + } + case 'o': + package_info.overlay = true; break; case '?': wantUsage = 1; 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 @@ public class AudioGroup { 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 @@ void AudioStream::decode(int tick) 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 @@ AudioGroup::~AudioGroup() 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 @@ bool AudioGroup::set(int sampleRate, int sampleCount) // 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 @@ bool AudioGroup::set(int sampleRate, int sampleCount) 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 @@ bool AudioGroup::remove(int socket) 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 @@ bool AudioGroup::deviceLoop() 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 @@ jint add(JNIEnv *env, jobject thiz, jint mode, 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 @@ jint add(JNIEnv *env, jobject thiz, jint mode, } 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 @@ jint add(JNIEnv *env, jobject thiz, jint mode, 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 @@ jint add(JNIEnv *env, jobject thiz, jint mode, // 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 @@ void sendDtmf(JNIEnv *env, jobject thiz, jint event) } 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}, |
