diff options
36 files changed, 449 insertions, 629 deletions
diff --git a/api/9.xml b/api/9.xml index f18623ff1e49..46f087fe9351 100644 --- a/api/9.xml +++ b/api/9.xml @@ -379555,7 +379555,7 @@ type="java.lang.String" transient="false" volatile="false" - value=""100-Continue"" + value=""100-continue"" static="true" final="true" deprecated="not deprecated" diff --git a/api/current.xml b/api/current.xml index f49477571b16..61f5e164bc11 100644 --- a/api/current.xml +++ b/api/current.xml @@ -403611,7 +403611,7 @@ type="java.lang.String" transient="false" volatile="false" - value=""100-Continue"" + value=""100-continue"" static="true" final="true" deprecated="not deprecated" diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index c88e0867ba80..c96d562ba6aa 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 e99d4b4dbbd5..2870c50b8658 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 81b28b9b3991..416f289f186a 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 9b9f796a1607..dc4e9c4e6525 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/hardware/Camera.java b/core/java/android/hardware/Camera.java index f72de6794375..a0abc6c0da9e 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -1138,9 +1138,9 @@ public class Camera { */ public static final String SCENE_MODE_BARCODE = "barcode"; - // Values for focus mode settings. /** - * Auto-focus mode. + * Auto-focus mode. Applications should call {@link + * #autoFocus(AutoFocusCallback)} to start the focus in this mode. */ public static final String FOCUS_MODE_AUTO = "auto"; @@ -1149,6 +1149,12 @@ public class Camera { * {@link #autoFocus(AutoFocusCallback)} in this mode. */ public static final String FOCUS_MODE_INFINITY = "infinity"; + + /** + * Macro (close-up) focus mode. Applications should call + * {@link #autoFocus(AutoFocusCallback)} to start the focus in this + * mode. + */ public static final String FOCUS_MODE_MACRO = "macro"; /** @@ -1170,7 +1176,9 @@ public class Camera { * Continuous auto focus mode. The camera continuously tries to focus. * This is ideal for shooting video or shooting photo of moving object. * Auto focus starts when the parameter is set. Applications should not - * call {@link #autoFocus(AutoFocusCallback)} in this mode. + * call {@link #autoFocus(AutoFocusCallback)} in this mode. To stop + * continuous focus, applications should change the focus mode to other + * modes. */ public static final String FOCUS_MODE_CONTINUOUS = "continuous"; @@ -1948,6 +1956,7 @@ public class Camera { * @see #FOCUS_MODE_INFINITY * @see #FOCUS_MODE_MACRO * @see #FOCUS_MODE_FIXED + * @see #FOCUS_MODE_EDOF * @see #FOCUS_MODE_CONTINUOUS */ public String getFocusMode() { diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index f6d237acde4b..d2c3eaab353b 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/DownloadManager.java b/core/java/android/net/DownloadManager.java index 447e64208ce2..cafe0f955245 100644 --- a/core/java/android/net/DownloadManager.java +++ b/core/java/android/net/DownloadManager.java @@ -51,14 +51,14 @@ public class DownloadManager { public final static String COLUMN_ID = "id"; /** - * The client-supplied title for this download. This will be displayed in system notifications, - * if enabled. + * The client-supplied title for this download. This will be displayed in system notifications. + * Defaults to the empty string. */ public final static String COLUMN_TITLE = "title"; /** * The client-supplied description of this download. This will be displayed in system - * notifications, if enabled. + * notifications. Defaults to the empty string. */ public final static String COLUMN_DESCRIPTION = "description"; @@ -68,22 +68,24 @@ public class DownloadManager { public final static String COLUMN_URI = "uri"; /** - * Internet Media Type of the downloaded file. This will be filled in based on the server's - * response once the download has started. + * Internet Media Type of the downloaded file. If no value is provided upon creation, this will + * initially be null and will be filled in based on the server's response once the download has + * started. * * @see <a href="http://www.ietf.org/rfc/rfc1590.txt">RFC 1590, defining Media Types</a> */ public final static String COLUMN_MEDIA_TYPE = "media_type"; /** - * Total size of the download in bytes. This will be filled in once the download starts. + * Total size of the download in bytes. This will initially be -1 and will be filled in once + * the download starts. */ public final static String COLUMN_TOTAL_SIZE_BYTES = "total_size"; /** * Uri where downloaded file will be stored. If a destination is supplied by client, that URI - * will be used here. Otherwise, the value will be filled in with a generated URI once the - * download has started. + * will be used here. Otherwise, the value will initially be null and will be filled in with a + * generated URI once the download has started. */ public final static String COLUMN_LOCAL_URI = "local_uri"; @@ -688,8 +690,13 @@ public class DownloadManager { if (column.equals(COLUMN_MEDIA_TYPE)) { return getUnderlyingString(Downloads.COLUMN_MIME_TYPE); } + assert column.equals(COLUMN_LOCAL_URI); - return Uri.fromFile(new File(getUnderlyingString(Downloads._DATA))).toString(); + String localUri = getUnderlyingString(Downloads._DATA); + if (localUri == null) { + return null; + } + return Uri.fromFile(new File(localUri)).toString(); } private long translateLong(String column) { diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index 214510d885d5..c34cb2f2f04f 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/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 2ca08ea8be29..402443cbdafb 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/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index 6a5d254b4005..99a3115bf2e9 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -337,11 +337,14 @@ public: static const char PIXEL_FORMAT_JPEG[]; // Values for focus mode settings. - // Auto-focus mode. + // Auto-focus mode. Applications should call + // CameraHardwareInterface.autoFocus to start the focus in this mode. static const char FOCUS_MODE_AUTO[]; // Focus is set at infinity. Applications should not call // CameraHardwareInterface.autoFocus in this mode. static const char FOCUS_MODE_INFINITY[]; + // Macro (close-up) focus mode. Applications should call + // CameraHardwareInterface.autoFocus to start the focus in this mode. static const char FOCUS_MODE_MACRO[]; // Focus is fixed. The camera is always in this mode if the focus is not // adjustable. If the camera has auto-focus, this mode can fix the @@ -355,7 +358,8 @@ public: // Continuous auto focus mode. The camera continuously tries to focus. This // is ideal for shooting video or shooting photo of moving object. Auto // focus starts when the parameter is set. Applications should not call - // CameraHardwareInterface.autoFocus in this mode. + // CameraHardwareInterface.autoFocus in this mode. To stop continuous + // focus, applications should change the focus mode to other modes. static const char FOCUS_MODE_CONTINUOUS[]; // The camera determines the exposure by giving more weight to the diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h index 313294152e47..3d428563359f 100644 --- a/include/ui/EventHub.h +++ b/include/ui/EventHub.h @@ -224,6 +224,7 @@ private: uint8_t* keyBitmask; KeyLayoutMap* layoutMap; String8 keylayoutFilename; + int fd; device_t* next; device_t(int32_t _id, const char* _path, const char* name); diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h index 2505cb0a89b4..aed4fa112b14 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 71c6c517692d..56d27651528a 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/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index 33393fe63f60..891661d690ac 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -60,7 +60,6 @@ #define ID_MASK 0x0000ffff #define SEQ_MASK 0x7fff0000 #define SEQ_SHIFT 16 -#define id_to_index(id) ((id&ID_MASK)+1) #ifndef ABS_MT_TOUCH_MAJOR #define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ @@ -87,7 +86,7 @@ static inline int max(int v1, int v2) EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name) : id(_id), path(_path), name(name), classes(0) - , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) { + , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), fd(-1), next(NULL) { } EventHub::device_t::~device_t() { @@ -152,9 +151,9 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis, struct input_absinfo info; - if(ioctl(mFDs[id_to_index(device->id)].fd, EVIOCGABS(axis), &info)) { + if(ioctl(device->fd, EVIOCGABS(axis), &info)) { LOGW("Error reading absolute controller %d for device %s fd %d\n", - axis, device->name.string(), mFDs[id_to_index(device->id)].fd); + axis, device->name.string(), device->fd); return -errno; } @@ -183,7 +182,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const { uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)]; memset(key_bitmask, 0, sizeof(key_bitmask)); - if (ioctl(mFDs[id_to_index(device->id)].fd, + if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP; } @@ -206,8 +205,7 @@ int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)]; memset(key_bitmask, 0, sizeof(key_bitmask)); - if (ioctl(mFDs[id_to_index(device->id)].fd, - EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { + if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) { #if 0 for (size_t i=0; i<=KEY_MAX; i++) { LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask)); @@ -243,7 +241,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const { uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)]; memset(sw_bitmask, 0, sizeof(sw_bitmask)); - if (ioctl(mFDs[id_to_index(device->id)].fd, + if (ioctl(device->fd, EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) { return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP; } @@ -583,7 +581,6 @@ 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; } } @@ -657,6 +654,7 @@ int EventHub::open_device(const char *deviceName) return -1; } + device->fd = fd; mFDs[mFDCount].fd = fd; mFDs[mFDCount].events = POLLIN; mFDs[mFDCount].revents = 0; @@ -814,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 13030b56e01f..ce616a475c42 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 5f5a4ac4e644..6f042ec7e8e4 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/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 6af3a7fd369e..12a1e6e16ac8 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -1273,6 +1273,14 @@ status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( hexdump(csd, csd_size); #endif + if (csd_size == 0) { + // There's no further information, i.e. no codec specific data + // Let's assume that the information provided in the mpeg4 headers + // is accurate and hope for the best. + + return OK; + } + if (csd_size < 2) { return ERROR_MALFORMED; } diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp index b699d8f51e6b..963009253018 100644 --- a/media/libstagefright/OggExtractor.cpp +++ b/media/libstagefright/OggExtractor.cpp @@ -158,7 +158,7 @@ status_t OggSource::read( ReadOptions::SeekMode mode; if (options && options->getSeekTo(&seekTimeUs, &mode)) { off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; - LOGI("seeking to offset %ld", pos); + LOGV("seeking to offset %ld", pos); if (mExtractor->mImpl->seekToOffset(pos) != OK) { return ERROR_END_OF_STREAM; @@ -267,7 +267,7 @@ ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { uint8_t header[27]; if (mSource->readAt(offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { - LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset); + LOGV("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset); return ERROR_IO; } @@ -384,7 +384,7 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { packetSize); if (n < (ssize_t)packetSize) { - LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); + LOGV("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); return ERROR_IO; } @@ -418,7 +418,7 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { buffer = NULL; } - LOGE("readPage returned %ld", n); + LOGV("readPage returned %ld", n); return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; } diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 5bbe441b13c8..9e256818e5d7 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/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index c2c799b4e0a0..f330d40a80f6 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 4762ddb4af09..9d31502fbca4 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 ba58b43e2df4..3addc0d2e208 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 79772edec355..a14bfb569b8b 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 166c52804e10..2eac0a80a08b 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 f2cfd2db579b..66bf5215d5d6 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 0291d7894b9a..000000000000 --- 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 c5d5c2b7f34b..000000000000 --- 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 3720e166992b..629d993ca007 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 188da6a784df..e1d283beddb7 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 043d54d96210..91ac915b7fb9 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 dd1cd05f1b93..22bf85706876 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 d25789726668..637ae48277b8 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 8e286e505d33..8ecfc018e4ea 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/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp index fc1ed9b06292..63a60eaa634c 100644 --- a/voip/jni/rtp/AudioGroup.cpp +++ b/voip/jni/rtp/AudioGroup.cpp @@ -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; |