diff options
100 files changed, 1998 insertions, 553 deletions
diff --git a/api/current.xml b/api/current.xml index 04d7a1d..7624086 100644 --- a/api/current.xml +++ b/api/current.xml @@ -221393,6 +221393,23 @@ <parameter name="id" type="java.lang.String"> </parameter> </method> +<method name="setInputMethodAndSubtype" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="token" type="android.os.IBinder"> +</parameter> +<parameter name="id" type="java.lang.String"> +</parameter> +<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype"> +</parameter> +</method> <method name="showInputMethodAndSubtypeEnabler" return="void" abstract="false" @@ -249195,7 +249212,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="t" type="T"> +<parameter name="arg0" type="T"> </parameter> </method> </interface> diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index 93baefd..f8650eb 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -98,3 +98,27 @@ LOCAL_MODULE_TAGS := debug LOCAL_MODULE:= audioloop include $(BUILD_EXECUTABLE) + +################################################################################ + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + stream.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libstagefright liblog libutils libbinder libsurfaceflinger_client \ + libstagefright_foundation libmedia + +LOCAL_C_INCLUDES:= \ + $(JNI_H_INCLUDE) \ + frameworks/base/media/libstagefright \ + $(TOP)/frameworks/base/include/media/stagefright/openmax + +LOCAL_CFLAGS += -Wno-multichar + +LOCAL_MODULE_TAGS := debug + +LOCAL_MODULE:= stream + +include $(BUILD_EXECUTABLE) diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp new file mode 100644 index 0000000..f2b5638 --- /dev/null +++ b/cmds/stagefright/stream.cpp @@ -0,0 +1,168 @@ +#include <binder/ProcessState.h> + +#include <media/IStreamSource.h> +#include <media/mediaplayer.h> +#include <media/stagefright/foundation/ADebug.h> + +#include <binder/IServiceManager.h> +#include <media/IMediaPlayerService.h> +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/SurfaceComposerClient.h> + +#include <fcntl.h> + +using namespace android; + +struct MyStreamSource : public BnStreamSource { + // Caller retains ownership of fd. + MyStreamSource(int fd); + + virtual void setListener(const sp<IStreamListener> &listener); + virtual void setBuffers(const Vector<sp<IMemory> > &buffers); + + virtual void onBufferAvailable(size_t index); + +protected: + virtual ~MyStreamSource(); + +private: + int mFd; + + sp<IStreamListener> mListener; + Vector<sp<IMemory> > mBuffers; + + DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource); +}; + +MyStreamSource::MyStreamSource(int fd) + : mFd(fd) { + CHECK_GE(fd, 0); +} + +MyStreamSource::~MyStreamSource() { +} + +void MyStreamSource::setListener(const sp<IStreamListener> &listener) { + mListener = listener; +} + +void MyStreamSource::setBuffers(const Vector<sp<IMemory> > &buffers) { + mBuffers = buffers; +} + +void MyStreamSource::onBufferAvailable(size_t index) { + CHECK_LT(index, mBuffers.size()); + sp<IMemory> mem = mBuffers.itemAt(index); + + ssize_t n = read(mFd, mem->pointer(), mem->size()); + if (n <= 0) { + mListener->queueCommand(IStreamListener::EOS); + } else { + mListener->queueBuffer(index, n); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +struct MyClient : public BnMediaPlayerClient { + MyClient() + : mEOS(false) { + } + + virtual void notify(int msg, int ext1, int ext2) { + Mutex::Autolock autoLock(mLock); + + if (msg == MEDIA_ERROR || msg == MEDIA_PLAYBACK_COMPLETE) { + mEOS = true; + mCondition.signal(); + } + } + + void waitForEOS() { + Mutex::Autolock autoLock(mLock); + while (!mEOS) { + mCondition.wait(mLock); + } + } + +protected: + virtual ~MyClient() { + } + +private: + Mutex mLock; + Condition mCondition; + + bool mEOS; + + DISALLOW_EVIL_CONSTRUCTORS(MyClient); +}; + +int main(int argc, char **argv) { + android::ProcessState::self()->startThreadPool(); + + if (argc != 2) { + fprintf(stderr, "Usage: %s filename\n", argv[0]); + return 1; + } + + sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient; + CHECK_EQ(composerClient->initCheck(), (status_t)OK); + + sp<SurfaceControl> control = + composerClient->createSurface( + getpid(), + String8("A Surface"), + 0, + 1280, + 800, + PIXEL_FORMAT_RGB_565, + 0); + + CHECK(control != NULL); + CHECK(control->isValid()); + + CHECK_EQ(composerClient->openTransaction(), (status_t)OK); + CHECK_EQ(control->setLayer(30000), (status_t)OK); + CHECK_EQ(control->show(), (status_t)OK); + CHECK_EQ(composerClient->closeTransaction(), (status_t)OK); + + sp<Surface> surface = control->getSurface(); + CHECK(surface != NULL); + + sp<IServiceManager> sm = defaultServiceManager(); + sp<IBinder> binder = sm->getService(String16("media.player")); + sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); + + CHECK(service.get() != NULL); + + int fd = open(argv[1], O_RDONLY); + + if (fd < 0) { + fprintf(stderr, "Failed to open file '%s'.", argv[1]); + return 1; + } + + sp<MyClient> client = new MyClient; + + sp<IMediaPlayer> player = + service->create(getpid(), client, new MyStreamSource(fd), 0); + + if (player != NULL) { + player->setVideoSurface(surface); + player->start(); + + client->waitForEOS(); + + player->stop(); + } else { + fprintf(stderr, "failed to instantiate player.\n"); + } + + close(fd); + fd = -1; + + composerClient->dispose(); + + return 0; +} diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 273e3c6..f3cc4ee 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -41,6 +41,7 @@ import android.os.StrictMode; import android.text.TextUtils; import android.util.Config; import android.util.Log; +import android.util.Singleton; import java.util.ArrayList; import java.util.List; @@ -52,8 +53,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM * Cast a Binder object into an activity manager interface, generating * a proxy if needed. */ - static public IActivityManager asInterface(IBinder obj) - { + static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } @@ -62,27 +62,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM if (in != null) { return in; } - + return new ActivityManagerProxy(obj); } - + /** * Retrieve the system's default/global activity manager. */ - static public IActivityManager getDefault() - { - if (gDefault != null) { - //if (Config.LOGV) Log.v( - // "ActivityManager", "returning cur default = " + gDefault); - return gDefault; - } - IBinder b = ServiceManager.getService("activity"); - if (Config.LOGV) Log.v( - "ActivityManager", "default service binder = " + b); - gDefault = asInterface(b); - if (Config.LOGV) Log.v( - "ActivityManager", "default service = " + gDefault); - return gDefault; + static public IActivityManager getDefault() { + return gDefault.get(); } /** @@ -95,13 +83,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return sSystemReady; } static boolean sSystemReady = false; - + /** * Convenience for sending a sticky broadcast. For internal use only. * If you don't care about permission, use null. */ - static public void broadcastStickyIntent(Intent intent, String permission) - { + static public void broadcastStickyIntent(Intent intent, String permission) { try { getDefault().broadcastIntent( null, intent, null, null, Activity.RESULT_OK, null, null, @@ -117,8 +104,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM } } - public ActivityManagerNative() - { + public ActivityManagerNative() { attachInterface(this, descriptor); } @@ -1390,16 +1376,27 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM } } - + return super.onTransact(code, data, reply, flags); } - public IBinder asBinder() - { + public IBinder asBinder() { return this; } - private static IActivityManager gDefault; + private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { + protected IActivityManager create() { + IBinder b = ServiceManager.getService("activity"); + if (Config.LOGV) { + Log.v("ActivityManager", "default service binder = " + b); + } + IActivityManager am = asInterface(b); + if (Config.LOGV) { + Log.v("ActivityManager", "default service = " + am); + } + return am; + } + }; } class ActivityManagerProxy implements IActivityManager diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index 09a21f8..4aa4d77 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -841,6 +841,12 @@ public class DownloadManager { } ContentValues values = new ContentValues(); values.put(Downloads.Impl.COLUMN_DELETED, 1); + // if only one id is passed in, then include it in the uri itself. + // this will eliminate a full database scan in the download service. + if (ids.length == 1) { + return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values, + null, null); + } return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids), getWhereArgsForIds(ids)); } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 556fb10..32df4e8 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -521,6 +521,21 @@ public final class BluetoothAdapter { } /** + * Get the UUIDs supported by the local Bluetooth adapter. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} + * + * @return the UUIDs supported by the local Bluetooth Adapter. + * @hide + */ + public ParcelUuid[] getUuids() { + try { + return mService.getUuids(); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return null; + } + + /** * Set the friendly Bluetooth name of the local Bluetooth adapter. * <p>This name is visible to remote Bluetooth devices. * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8 diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java index 138e7f2..3eadff9 100644 --- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java +++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java @@ -301,10 +301,9 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine if (isPhoneDocked(mDevice)) { // Don't auto connect to docks. break; - } else if (mHeadsetService == null) { - deferMessage(message); } else { - if (mHeadsetService.getPriority(mDevice) == + if (mHeadsetService != null && + mHeadsetService.getPriority(mDevice) == BluetoothHeadset.PRIORITY_AUTO_CONNECT && mHeadsetService.getDevicesMatchingConnectionStates( new int[] {BluetoothProfile.STATE_CONNECTED, @@ -1027,7 +1026,8 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine // This is again against spec. HFP incoming connections should be made // before A2DP, so we should not hit this case. But many devices // don't follow this. - if (mHeadsetService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON) { + if (mHeadsetService != null && + mHeadsetService.getPriority(mDevice) == BluetoothProfile.PRIORITY_ON) { Message msg = new Message(); msg.what = CONNECT_OTHER_PROFILES; msg.arg1 = CONNECT_HFP_OUTGOING; diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index aefb3f2..f3e73cf 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -35,6 +35,7 @@ interface IBluetooth String getAddress(); String getName(); boolean setName(in String name); + ParcelUuid[] getUuids(); int getScanMode(); boolean setScanMode(int mode, int duration); diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java index d360140..898c642 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -17,7 +17,9 @@ package android.os; import android.util.Config; +import android.util.Log; import android.util.Printer; +import android.util.PrefixPrinter; /** * Class used to run a message loop for a thread. Threads by default do @@ -31,37 +33,38 @@ import android.util.Printer; * <p>This is a typical example of the implementation of a Looper thread, * using the separation of {@link #prepare} and {@link #loop} to create an * initial Handler to communicate with the Looper. - * + * * <pre> * class LooperThread extends Thread { * public Handler mHandler; - * + * * public void run() { * Looper.prepare(); - * + * * mHandler = new Handler() { * public void handleMessage(Message msg) { * // process incoming messages here * } * }; - * + * * Looper.loop(); * } * }</pre> */ public class Looper { - private static final boolean DEBUG = false; - private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; + private static final String TAG = "Looper"; + private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE); // sThreadLocal.get() will return null unless you've called prepare(). - private static final ThreadLocal sThreadLocal = new ThreadLocal(); + private static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); final MessageQueue mQueue; + final Thread mThread; volatile boolean mRun; - Thread mThread; + private Printer mLogging = null; - private static Looper mMainLooper = null; - + private static Looper mMainLooper = null; // guarded by Looper.class + /** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call @@ -74,13 +77,13 @@ public class Looper { } sThreadLocal.set(new Looper()); } - - /** Initialize the current thread as a looper, marking it as an application's main - * looper. The main looper for your application is created by the Android environment, - * so you should never need to call this function yourself. - * {@link #prepare()} + + /** + * Initialize the current thread as a looper, marking it as an + * application's main looper. The main looper for your application + * is created by the Android environment, so you should never need + * to call this function yourself. See also: {@link #prepare()} */ - public static final void prepareMainLooper() { prepare(); setMainLooper(myLooper()); @@ -92,7 +95,7 @@ public class Looper { private synchronized static void setMainLooper(Looper looper) { mMainLooper = looper; } - + /** Returns the application's main looper, which lives in the main thread of the application. */ public synchronized static final Looper getMainLooper() { @@ -100,28 +103,28 @@ public class Looper { } /** - * Run the message queue in this thread. Be sure to call + * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static final void loop() { Looper me = myLooper(); + if (me == null) { + throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); + } MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block - //if (!me.mRun) { - // break; - //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } - if (me.mLogging!= null) me.mLogging.println( + if (me.mLogging != null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); - if (me.mLogging!= null) me.mLogging.println( + if (me.mLogging != null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); @@ -134,7 +137,7 @@ public class Looper { * null if the calling thread is not associated with a Looper. */ public static final Looper myLooper() { - return (Looper)sThreadLocal.get(); + return sThreadLocal.get(); } /** @@ -179,28 +182,29 @@ public class Looper { public Thread getThread() { return mThread; } - + /** @hide */ public MessageQueue getQueue() { return mQueue; } - + public void dump(Printer pw, String prefix) { - pw.println(prefix + this); - pw.println(prefix + "mRun=" + mRun); - pw.println(prefix + "mThread=" + mThread); - pw.println(prefix + "mQueue=" + ((mQueue != null) ? mQueue : "(null")); + pw = PrefixPrinter.create(pw, prefix); + pw.println(this.toString()); + pw.println("mRun=" + mRun); + pw.println("mThread=" + mThread); + pw.println("mQueue=" + ((mQueue != null) ? mQueue : "(null")); if (mQueue != null) { synchronized (mQueue) { long now = SystemClock.uptimeMillis(); Message msg = mQueue.mMessages; int n = 0; while (msg != null) { - pw.println(prefix + " Message " + n + ": " + msg.toString(now)); + pw.println(" Message " + n + ": " + msg.toString(now)); n++; msg = msg.next; } - pw.println(prefix + "(Total messages: " + n + ")"); + pw.println("(Total messages: " + n + ")"); } } } @@ -226,4 +230,3 @@ public class Looper { } } } - diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index b69e0b1..754d073 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -19,6 +19,7 @@ import android.animation.ValueAnimator; import android.app.ActivityManagerNative; import android.app.ActivityThread; import android.app.ApplicationErrorReport; +import android.app.IActivityManager; import android.content.Intent; import android.util.Log; import android.util.Printer; @@ -112,6 +113,13 @@ public final class StrictMode { private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE); private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE); + /** + * The boolean system property to control screen flashes on violations. + * + * @hide + */ + public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual"; + // Only log a duplicate stack trace to the logs every second. private static final long MIN_LOG_INTERVAL_MS = 1000; @@ -711,29 +719,66 @@ public final class StrictMode { return new ThreadPolicy(oldPolicyMask); } + // We don't want to flash the screen red in the system server + // process, nor do we want to modify all the call sites of + // conditionallyEnableDebugLogging() in the system server, + // so instead we use this to determine if we are the system server. + private static boolean amTheSystemServerProcess() { + // Fast path. Most apps don't have the system server's UID. + if (Process.myUid() != Process.SYSTEM_UID) { + return false; + } + + // The settings app, though, has the system server's UID so + // look up our stack to see if we came from the system server. + Throwable stack = new Throwable(); + stack.fillInStackTrace(); + for (StackTraceElement ste : stack.getStackTrace()) { + String clsName = ste.getClassName(); + if (clsName != null && clsName.startsWith("com.android.server.")) { + return true; + } + } + return false; + } + /** * Enable DropBox logging for debug phone builds. * * @hide */ public static boolean conditionallyEnableDebugLogging() { + boolean doFlashes = !amTheSystemServerProcess() && + SystemProperties.getBoolean(VISUAL_PROPERTY, IS_ENG_BUILD); + // For debug builds, log event loop stalls to dropbox for analysis. // Similar logic also appears in ActivityThread.java for system apps. - if (IS_USER_BUILD) { + if (IS_USER_BUILD && !doFlashes) { setCloseGuardEnabled(false); return false; } - StrictMode.setThreadPolicyMask( - StrictMode.DETECT_DISK_WRITE | - StrictMode.DETECT_DISK_READ | - StrictMode.DETECT_NETWORK | - StrictMode.PENALTY_DROPBOX | - (IS_ENG_BUILD ? StrictMode.PENALTY_FLASH : 0) - ); - sVmPolicyMask = StrictMode.DETECT_VM_CURSOR_LEAKS | - StrictMode.DETECT_VM_CLOSABLE_LEAKS | - StrictMode.PENALTY_DROPBOX; - setCloseGuardEnabled(vmClosableObjectLeaksEnabled()); + + int threadPolicyMask = StrictMode.DETECT_DISK_WRITE | + StrictMode.DETECT_DISK_READ | + StrictMode.DETECT_NETWORK; + + if (!IS_USER_BUILD) { + threadPolicyMask |= StrictMode.PENALTY_DROPBOX; + } + if (doFlashes) { + threadPolicyMask |= StrictMode.PENALTY_FLASH; + } + + StrictMode.setThreadPolicyMask(threadPolicyMask); + + if (IS_USER_BUILD) { + setCloseGuardEnabled(false); + } else { + sVmPolicyMask = StrictMode.DETECT_VM_CURSOR_LEAKS | + StrictMode.DETECT_VM_CLOSABLE_LEAKS | + StrictMode.PENALTY_DROPBOX; + setCloseGuardEnabled(vmClosableObjectLeaksEnabled()); + } return true; } @@ -1091,11 +1136,15 @@ public final class StrictMode { public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); try { - ActivityManagerNative.getDefault(). - handleApplicationStrictModeViolation( - RuntimeInit.getApplicationObject(), - violationMaskSubset, - info); + IActivityManager am = ActivityManagerNative.getDefault(); + if (am == null) { + Log.d(TAG, "No activity manager; failed to Dropbox violation."); + } else { + am.handleApplicationStrictModeViolation( + RuntimeInit.getApplicationObject(), + violationMaskSubset, + info); + } } catch (RemoteException e) { Log.e(TAG, "RemoteException handling StrictMode violation", e); } diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index 4a036ec..619bf8d 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -93,7 +93,7 @@ public class SystemProperties * Get the value for the given key, returned as a boolean. * Values 'n', 'no', '0', 'false' or 'off' are considered false. * Values 'y', 'yes', '1', 'true' or 'on' are considered true. - * (case insensitive). + * (case sensitive). * If the key does not exist, or has any other value, then the default * result is returned. * @param key the key to lookup diff --git a/core/java/android/preference/PreferenceFrameLayout.java b/core/java/android/preference/PreferenceFrameLayout.java index 426abf0..481859e 100644 --- a/core/java/android/preference/PreferenceFrameLayout.java +++ b/core/java/android/preference/PreferenceFrameLayout.java @@ -45,12 +45,18 @@ public class PreferenceFrameLayout extends FrameLayout { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.PreferenceFrameLayout, defStyle, 0); - mTopPadding = (int) a.getDimension( + float density = context.getResources().getDisplayMetrics().density; + int defaultTopPadding = (int) (density * DEFAULT_TOP_PADDING + 0.5f); + int defaultBottomPadding = (int) (density * DEFAULT_BOTTOM_PADDING + 0.5f); + + mTopPadding = a.getDimensionPixelSize( com.android.internal.R.styleable.PreferenceFrameLayout_topPadding, - DEFAULT_TOP_PADDING); - mBottomPadding = (int) a.getDimension( + defaultTopPadding); + mBottomPadding = a.getDimensionPixelSize( com.android.internal.R.styleable.PreferenceFrameLayout_bottomPadding, - DEFAULT_BOTTOM_PADDING); + defaultBottomPadding); + + a.recycle(); } diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java index ff769ad..683e603 100644 --- a/core/java/android/provider/Downloads.java +++ b/core/java/android/provider/Downloads.java @@ -382,6 +382,27 @@ public final class Downloads { */ public static final String COLUMN_ERROR_MSG = "errorMsg"; + /** + * This column stores the source of the last update to this row. + * This column is only for internal use. + * Valid values are indicated by LAST_UPDATESRC_* constants. + * <P>Type: INT</P> + */ + public static final String COLUMN_LAST_UPDATESRC = "lastUpdateSrc"; + + /** + * default value for {@link #COLUMN_LAST_UPDATESRC}. + * This value is used when this column's value is not relevant. + */ + public static final int LAST_UPDATESRC_NOT_RELEVANT = 0; + + /** + * One of the values taken by {@link #COLUMN_LAST_UPDATESRC}. + * This value is used when the update is NOT to be relayed to the DownloadService + * (and thus spare DownloadService from scanning the database when this change occurs) + */ + public static final int LAST_UPDATESRC_DONT_NOTIFY_DOWNLOADSVC = 1; + /* * Lists the destinations that an application can specify for a download. */ diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index 01a6b94..398b5ae 100644 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -541,14 +541,15 @@ public class BluetoothService extends IBluetooth.Stub { mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 3, -1), 500); break; case 3: - Log.d(TAG, "Registering opush record"); - SystemService.start("opush"); + Log.d(TAG, "Registering pbap record"); + SystemService.start("pbap"); mHandler.sendMessageDelayed( - mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 500); + mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 500); + break; case 4: - Log.d(TAG, "Registering pbap record"); - SystemService.start("pbap"); + Log.d(TAG, "Registering opush record"); + SystemService.start("opush"); break; } break; @@ -630,8 +631,15 @@ public class BluetoothService extends IBluetooth.Stub { initProfileState(); //Register SDP records. - mHandler.sendMessageDelayed( + if (mContext.getResources(). + getBoolean(com.android.internal.R.bool.config_voice_capable)) { + mHandler.sendMessageDelayed( mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 1, -1), 3000); + } else { + // Register only OPP. + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS, 4, -1), 3000); + } setBluetoothTetheringNative(true, BluetoothPan.NAP_ROLE, BluetoothPan.NAP_BRIDGE); @@ -1196,6 +1204,24 @@ public class BluetoothService extends IBluetooth.Stub { return getProperty("Name"); } + public synchronized ParcelUuid[] getUuids() { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + String value = getProperty("UUIDs"); + if (value == null) return null; + + String[] uuidStrings = null; + // The UUIDs are stored as a "," separated string. + uuidStrings = value.split(","); + ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length]; + + for (int i = 0; i < uuidStrings.length; i++) { + uuids[i] = ParcelUuid.fromString(uuidStrings[i]); + } + return uuids; + + } + + /** * Returns the user-friendly name of a remote device. This value is * returned from our local cache, which is updated when onPropertyChange diff --git a/core/java/android/util/PrefixPrinter.java b/core/java/android/util/PrefixPrinter.java new file mode 100644 index 0000000..62f7da1 --- /dev/null +++ b/core/java/android/util/PrefixPrinter.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +/** + * PrefixPrinter is a Printer which prefixes all lines with a given + * prefix. + * + * @hide + */ +public class PrefixPrinter implements Printer { + private final Printer mPrinter; + private final String mPrefix; + + /** + * Creates a new PrefixPrinter. + * + * <p>If prefix is null or empty, the provided printer is returned, rather + * than making a prefixing printer. + */ + public static Printer create(Printer printer, String prefix) { + if (prefix == null || prefix.equals("")) { + return printer; + } + return new PrefixPrinter(printer, prefix); + } + + private PrefixPrinter(Printer printer, String prefix) { + mPrinter = printer; + mPrefix = prefix; + } + + public void println(String str) { + mPrinter.println(mPrefix + str); + } +} diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 60ca384..85ce5e1 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -158,18 +158,17 @@ public class TimeUtils { static private int printField(char[] formatStr, int amt, char suffix, int pos, boolean always, int zeropad) { if (always || amt > 0) { + final int startPos = pos; if ((always && zeropad >= 3) || amt > 99) { int dig = amt/100; formatStr[pos] = (char)(dig + '0'); pos++; - always = true; amt -= (dig*100); } - if ((always && zeropad >= 2) || amt > 9) { + if ((always && zeropad >= 2) || amt > 9 || startPos != pos) { int dig = amt/10; formatStr[pos] = (char)(dig + '0'); pos++; - always = true; amt -= (dig*10); } formatStr[pos] = (char)(amt + '0'); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index d964e2f..beda099 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -140,6 +140,12 @@ interface IWindowManager // on screen) void showStrictModeViolation(boolean on); + // Proxy to set the system property for whether the flashing + // should be enabled. The 'enabled' value is null or blank for + // the system default (differs per build variant) or any valid + // boolean string as parsed by SystemProperties.getBoolean(). + void setStrictModeVisualIndicatorPreference(String enabled); + // These can only be called with the SET_ORIENTATION permission. /** * Change the current screen rotation, constants as per diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index d596a7f..e967522 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -374,6 +374,19 @@ public class Surface implements Parcelable { } /** + * Copy the current screen contents into a bitmap and return it. + * + * @param width The desired width of the returned bitmap; the raw + * screen will be scaled down to this size. + * @param height The desired height of the returned bitmap; the raw + * screen will be scaled down to this size. + * @return Returns a Bitmap containing the screen contents. + * + * @hide + */ + public static native Bitmap screenshot(int width, int height); + + /** * set surface parameters. * needs to be inside open/closeTransaction block */ diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 784951f..51016f5 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -171,6 +171,7 @@ public interface WindowManager extends ViewManager { @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"), @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"), @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL, to = "TYPE_STATUS_BAR_PANEL"), + @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL, to = "TYPE_STATUS_BAR_SUB_PANEL"), @ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG, to = "TYPE_SYSTEM_DIALOG"), @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, to = "TYPE_KEYGUARD_DIALOG"), @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"), @@ -351,7 +352,7 @@ public interface WindowManager extends ViewManager { public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13; /** - * Window type: panel that slides out from the status bar + * Window type: panel that slides out from over the status bar */ public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14; @@ -375,6 +376,13 @@ public interface WindowManager extends ViewManager { public static final int TYPE_DRAG = FIRST_SYSTEM_WINDOW+16; /** + * Window type: panel that slides out from under the status bar + * @hide + */ + public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17; + + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 621a908..9bc1c22 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -1278,10 +1278,10 @@ public final class InputMethodManager { } } } - + /** - * Force switch to a new input method component. This can only be called - * from the currently active input method, as validated by the given token. + * Force switch to a new input method component. This can only be called + * from an application or a service which has a token of the currently active input method. * @param token Supplies the identifying token given to an input method * when it was started, which allows it to perform this operation on * itself. @@ -1294,7 +1294,24 @@ public final class InputMethodManager { throw new RuntimeException(e); } } - + + /** + * Force switch to a new input method and subtype. This can only be called + * from an application or a service which has a token of the currently active input method. + * @param token Supplies the identifying token given to an input method + * when it was started, which allows it to perform this operation on + * itself. + * @param id The unique identifier for the new input method to be switched to. + * @param subtype The new subtype of the new input method to be switched to. + */ + public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) { + try { + mService.setInputMethodAndSubtype(token, id, subtype); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + /** * Close/hide the input method's soft input area, so the user no longer * sees it or can interact with it. This can only be called diff --git a/core/java/android/webkit/OverScrollGlow.java b/core/java/android/webkit/OverScrollGlow.java index 53600f6..af56a2f 100644 --- a/core/java/android/webkit/OverScrollGlow.java +++ b/core/java/android/webkit/OverScrollGlow.java @@ -17,6 +17,7 @@ package android.webkit; import com.android.internal.R; +import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.drawable.Drawable; @@ -40,13 +41,14 @@ public class OverScrollGlow { public OverScrollGlow(WebView host) { mHostView = host; - final Resources res = host.getContext().getResources(); + Context context = host.getContext(); + final Resources res = context.getResources(); final Drawable edge = res.getDrawable(R.drawable.overscroll_edge); final Drawable glow = res.getDrawable(R.drawable.overscroll_glow); - mEdgeGlowTop = new EdgeGlow(edge, glow); - mEdgeGlowBottom = new EdgeGlow(edge, glow); - mEdgeGlowLeft = new EdgeGlow(edge, glow); - mEdgeGlowRight = new EdgeGlow(edge, glow); + mEdgeGlowTop = new EdgeGlow(context, edge, glow); + mEdgeGlowBottom = new EdgeGlow(context, edge, glow); + mEdgeGlowLeft = new EdgeGlow(context, edge, glow); + mEdgeGlowRight = new EdgeGlow(context, edge, glow); } /** diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 9b519c2..56325f6 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -3050,10 +3050,10 @@ public class WebView extends AbsoluteLayout } else { mScrollX = x; mScrollY = y; - if (mScroller.getStartX() != mScrollX || mScroller.getStartY() != mScrollY) { - abortAnimation(); - mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY); - WebViewCore.resumePriority(); + abortAnimation(); + mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY); + WebViewCore.resumePriority(); + if (!mSelectingText) { WebViewCore.resumeUpdatePicture(mWebViewCore); } } @@ -3820,7 +3820,9 @@ public class WebView extends AbsoluteLayout } void onFixedLengthZoomAnimationEnd() { - WebViewCore.resumeUpdatePicture(mWebViewCore); + if (!mSelectingText) { + WebViewCore.resumeUpdatePicture(mWebViewCore); + } onZoomAnimationEnd(); } @@ -4649,6 +4651,7 @@ public class WebView extends AbsoluteLayout // called by mSelectCallback.onDestroyActionMode mSelectCallback.finish(); mSelectCallback = null; + WebViewCore.resumePriority(); WebViewCore.resumeUpdatePicture(mWebViewCore); invalidate(); // redraw without selection } @@ -5554,7 +5557,9 @@ public class WebView extends AbsoluteLayout // is possible on emulator. mLastVelocity = 0; WebViewCore.resumePriority(); - WebViewCore.resumeUpdatePicture(mWebViewCore); + if (!mSelectingText) { + WebViewCore.resumeUpdatePicture(mWebViewCore); + } break; } stopTouch(); @@ -5683,8 +5688,8 @@ public class WebView extends AbsoluteLayout mVelocityTracker = null; } - if (mTouchMode == TOUCH_DRAG_MODE || - mTouchMode == TOUCH_DRAG_LAYER_MODE) { + if ((mTouchMode == TOUCH_DRAG_MODE + || mTouchMode == TOUCH_DRAG_LAYER_MODE) && !mSelectingText) { WebViewCore.resumePriority(); WebViewCore.resumeUpdatePicture(mWebViewCore); } @@ -6055,7 +6060,9 @@ public class WebView extends AbsoluteLayout } if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) { WebViewCore.resumePriority(); - WebViewCore.resumeUpdatePicture(mWebViewCore); + if (!mSelectingText) { + WebViewCore.resumeUpdatePicture(mWebViewCore); + } if (mScroller.springBack(mScrollX, mScrollY, 0, computeMaxScrollX(), 0, computeMaxScrollY())) { invalidate(); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 423a788..4ff7ee8 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -132,7 +132,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * Indicates the touch gesture is a scroll */ static final int TOUCH_MODE_SCROLL = 3; - + /** * Indicates the view is in the process of being flung */ @@ -385,7 +385,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * Handles one frame of a fling */ private FlingRunnable mFlingRunnable; - + /** * Handles scrolling between positions within the list. */ @@ -456,7 +456,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te int mResurrectToPosition = INVALID_POSITION; private ContextMenuInfo mContextMenuInfo = null; - + /** * Maximum distance to record overscroll */ @@ -550,19 +550,19 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te private int mMinimumVelocity; private int mMaximumVelocity; private float mVelocityScale = 1.0f; - + final boolean[] mIsScrap = new boolean[1]; - + // True when the popup should be hidden because of a call to // dispatchDisplayHint() private boolean mPopupHidden; - + /** * ID of the active pointer. This is used to retain consistency during * drags/flings if multiple pointers are used. */ private int mActivePointerId = INVALID_POINTER; - + /** * Sentinel value for no current active pointer. * Used by {@link #mActivePointerId}. @@ -726,7 +726,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te boolean smoothScrollbar = a.getBoolean(R.styleable.AbsListView_smoothScrollbar, true); setSmoothScrollbarEnabled(smoothScrollbar); - + final int adapterId = a.getResourceId(R.styleable.AbsListView_adapter, 0); if (adapterId != 0) { final Context c = context; @@ -764,11 +764,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te public void setOverScrollMode(int mode) { if (mode != OVER_SCROLL_NEVER) { if (mEdgeGlowTop == null) { - final Resources res = getContext().getResources(); + Context context = getContext(); + final Resources res = context.getResources(); final Drawable edge = res.getDrawable(R.drawable.overscroll_edge); final Drawable glow = res.getDrawable(R.drawable.overscroll_glow); - mEdgeGlowTop = new EdgeGlow(edge, glow); - mEdgeGlowBottom = new EdgeGlow(edge, glow); + mEdgeGlowTop = new EdgeGlow(context, edge, glow); + mEdgeGlowBottom = new EdgeGlow(context, edge, glow); } } else { mEdgeGlowTop = null; @@ -1843,7 +1844,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @param position The position to display * @param isScrap Array of at least 1 boolean, the first entry will become true if * the returned view was taken from the scrap heap, false if otherwise. - * + * * @return A view displaying the data associated with the specified position */ View obtainView(int position, boolean[] isScrap) { @@ -2166,7 +2167,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te treeObserver.addOnGlobalLayoutListener(this); } } - + if (mAdapter != null && mDataSetObserver == null) { mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver); @@ -2962,7 +2963,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mFlingRunnable = new FlingRunnable(); } reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); - + mFlingRunnable.start(-initialVelocity); } else { mTouchMode = TOUCH_MODE_REST; @@ -3015,7 +3016,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mVelocityTracker.recycle(); mVelocityTracker = null; } - + mActivePointerId = INVALID_POINTER; if (PROFILE_SCROLLING) { @@ -3064,7 +3065,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mVelocityTracker = null; } } - + if (mEdgeGlowTop != null) { mEdgeGlowTop.onRelease(); mEdgeGlowBottom.onRelease(); @@ -3072,7 +3073,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mActivePointerId = INVALID_POINTER; break; } - + case MotionEvent.ACTION_POINTER_UP: { onSecondaryPointerUp(ev); final int x = mMotionX; @@ -3170,11 +3171,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionCorrection = 0; return true; } - + final int x = (int) ev.getX(); final int y = (int) ev.getY(); mActivePointerId = ev.getPointerId(0); - + int motionPosition = findMotionRow(y); if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) { // User clicked on an actual view (and was not stopping a fling). @@ -3213,7 +3214,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); break; } - + case MotionEvent.ACTION_POINTER_UP: { onSecondaryPointerUp(ev); break; @@ -3222,7 +3223,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te return false; } - + private void onSecondaryPointerUp(MotionEvent ev) { final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; @@ -3418,7 +3419,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te default: endFling(); return; - + case TOUCH_MODE_SCROLL: if (mScroller.isFinished()) { return; @@ -3521,17 +3522,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } - - + + class PositionScroller implements Runnable { private static final int SCROLL_DURATION = 400; - + private static final int MOVE_DOWN_POS = 1; private static final int MOVE_UP_POS = 2; private static final int MOVE_DOWN_BOUND = 3; private static final int MOVE_UP_BOUND = 4; private static final int MOVE_OFFSET = 5; - + private int mMode; private int mTargetPos; private int mBoundPos; @@ -3540,17 +3541,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te private final int mExtraScroll; private int mOffsetFromTop; - + PositionScroller() { mExtraScroll = ViewConfiguration.get(mContext).getScaledFadingEdgeLength(); } - + void start(int position) { final int firstPos = mFirstPosition; final int lastPos = firstPos + getChildCount() - 1; - + int viewTravelCount; - if (position <= firstPos) { + if (position <= firstPos) { viewTravelCount = firstPos - position + 1; mMode = MOVE_UP_POS; } else if (position >= lastPos) { @@ -3560,7 +3561,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // Already on screen, nothing to do return; } - + if (viewTravelCount > 0) { mScrollDuration = SCROLL_DURATION / viewTravelCount; } else { @@ -3569,19 +3570,19 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mTargetPos = position; mBoundPos = INVALID_POSITION; mLastSeenPos = INVALID_POSITION; - + post(this); } - + void start(int position, int boundPosition) { if (boundPosition == INVALID_POSITION) { start(position); return; } - + final int firstPos = mFirstPosition; final int lastPos = firstPos + getChildCount() - 1; - + int viewTravelCount; if (position <= firstPos) { final int boundPosFromLast = lastPos - boundPosition; @@ -3589,7 +3590,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // Moving would shift our bound position off the screen. Abort. return; } - + final int posTravel = firstPos - position + 1; final int boundTravel = boundPosFromLast - 1; if (boundTravel < posTravel) { @@ -3619,7 +3620,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // Already on screen, nothing to do return; } - + if (viewTravelCount > 0) { mScrollDuration = SCROLL_DURATION / viewTravelCount; } else { @@ -3628,7 +3629,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mTargetPos = position; mBoundPos = boundPosition; mLastSeenPos = INVALID_POSITION; - + post(this); } @@ -3679,12 +3680,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int listHeight = getHeight(); final int firstPos = mFirstPosition; - + switch (mMode) { case MOVE_DOWN_POS: { final int lastViewIndex = getChildCount() - 1; final int lastPos = firstPos + lastViewIndex; - + if (lastViewIndex < 0) { return; } @@ -3710,11 +3711,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } break; } - + case MOVE_DOWN_BOUND: { final int nextViewIndex = 1; final int childCount = getChildCount(); - + if (firstPos == mBoundPos || childCount <= nextViewIndex || firstPos + childCount >= mItemCount) { return; @@ -3739,13 +3740,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te post(this); } else { - if (nextViewTop > extraScroll) { + if (nextViewTop > extraScroll) { smoothScrollBy(nextViewTop - extraScroll, mScrollDuration); } } break; } - + case MOVE_UP_POS: { if (firstPos == mLastSeenPos) { // No new views, let things keep going. @@ -3769,7 +3770,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } break; } - + case MOVE_UP_BOUND: { final int lastViewIndex = getChildCount() - 2; if (lastViewIndex < 0) { @@ -3835,11 +3836,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } - + /** * The amount of friction applied to flings. The default value * is {@link ViewConfiguration#getScrollFriction}. - * + * * @return A scalar dimensionless value representing the coefficient of * friction. */ @@ -3847,19 +3848,19 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (mFlingRunnable == null) { mFlingRunnable = new FlingRunnable(); } - mFlingRunnable.mScroller.setFriction(friction); + mFlingRunnable.mScroller.setFriction(friction); } /** * Sets a scale factor for the fling velocity. The initial scale * factor is 1.0. - * + * * @param scale The scale factor to multiply the velocity by. */ public void setVelocityScale(float scale) { mVelocityScale = scale; } - + /** * Smoothly scroll to the specified adapter position. The view will * scroll such that the indicated position is displayed. @@ -3913,7 +3914,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * Smoothly scroll to the specified adapter position. The view will * scroll such that the indicated position is displayed, but it will * stop early if scrolling further would scroll boundPosition out of - * view. + * view. * @param position Scroll to this adapter position. * @param boundPosition Do not scroll if it would move this adapter * position out of view. @@ -3924,7 +3925,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } mPositionScroller.start(position, boundPosition); } - + /** * Smoothly scroll by distance pixels over duration milliseconds. * @param distance Distance to scroll in pixels. @@ -4145,7 +4146,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (down) { mFirstPosition += count; } - + invalidate(); final int absIncrementalDeltaY = Math.abs(incrementalDeltaY); @@ -4171,7 +4172,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te invokeOnItemScrollListener(); awakenScrollBars(); - + return false; } @@ -5289,7 +5290,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mCurrentScrap = scrapViews[0]; mScrapViews = scrapViews; } - + public void markChildrenDirty() { if (mViewTypeCount == 1) { final ArrayList<View> scrap = mCurrentScrap; diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java index 9b3a6e6..2a0e849 100644 --- a/core/java/android/widget/EdgeGlow.java +++ b/core/java/android/widget/EdgeGlow.java @@ -16,6 +16,7 @@ package android.widget; +import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.view.animation.AnimationUtils; @@ -44,7 +45,7 @@ public class EdgeGlow { private static final float HELD_GLOW_ALPHA = 0.5f; private static final float HELD_GLOW_SCALE_Y = 0.5f; - private static final float MAX_GLOW_HEIGHT = 3.f; + private static final float MAX_GLOW_HEIGHT = 4.f; private static final float PULL_GLOW_BEGIN = 1.f; private static final float PULL_EDGE_BEGIN = 0.6f; @@ -58,6 +59,8 @@ public class EdgeGlow { private final Drawable mGlow; private int mWidth; private int mHeight; + private final int MIN_WIDTH = 300; + private final int mMinWidth; private float mEdgeAlpha; private float mEdgeScaleY; @@ -86,12 +89,12 @@ public class EdgeGlow { // How much dragging should effect the height of the edge image. // Number determined by user testing. - private static final int PULL_DISTANCE_EDGE_FACTOR = 5; + private static final int PULL_DISTANCE_EDGE_FACTOR = 7; // How much dragging should effect the height of the glow image. // Number determined by user testing. - private static final int PULL_DISTANCE_GLOW_FACTOR = 5; - private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 0.8f; + private static final int PULL_DISTANCE_GLOW_FACTOR = 7; + private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f; private static final int VELOCITY_EDGE_FACTOR = 8; private static final int VELOCITY_GLOW_FACTOR = 16; @@ -100,10 +103,11 @@ public class EdgeGlow { private float mPullDistance; - public EdgeGlow(Drawable edge, Drawable glow) { + public EdgeGlow(Context context, Drawable edge, Drawable glow) { mEdge = edge; mGlow = glow; + mMinWidth = (int) (context.getResources().getDisplayMetrics().density * MIN_WIDTH + 0.5f); mInterpolator = new DecelerateInterpolator(); } @@ -251,17 +255,31 @@ public class EdgeGlow { mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255)); - // Center the glow inside the width of the container. - int glowLeft = (mWidth - glowWidth)/2; - mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, (int) Math.min( + int glowBottom = (int) Math.min( glowHeight * mGlowScaleY * glowHeight/ glowWidth * 0.6f, - glowHeight * MAX_GLOW_HEIGHT)); + glowHeight * MAX_GLOW_HEIGHT); + if (mWidth < mMinWidth) { + // Center the glow and clip it. + int glowLeft = (mWidth - glowWidth)/2; + mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom); + } else { + // Stretch the glow to fit. + mGlow.setBounds(0, 0, mWidth, glowBottom); + } + mGlow.draw(canvas); mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255)); - int edgeLeft = (mWidth - edgeWidth)/2; - mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, (int) (edgeHeight * mEdgeScaleY)); + int edgeBottom = (int) (edgeHeight * mEdgeScaleY); + if (mWidth < mMinWidth) { + // Center the edge and clip it. + int edgeLeft = (mWidth - edgeWidth)/2; + mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom); + } else { + // Stretch the edge to fit. + mEdge.setBounds(0, 0, mWidth, edgeBottom); + } mEdge.draw(canvas); return mState != STATE_IDLE; diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 9fc91da..c05e3ad 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -58,8 +58,8 @@ import java.util.List; * within a larger container. * * <p>HorizontalScrollView only supports horizontal scrolling. - * - * @attr ref android.R.styleable#HorizontalScrollView_fillViewport + * + * @attr ref android.R.styleable#HorizontalScrollView_fillViewport */ public class HorizontalScrollView extends FrameLayout { private static final int ANIMATED_SCROLL_GAP = ScrollView.ANIMATED_SCROLL_GAP; @@ -125,7 +125,7 @@ public class HorizontalScrollView extends FrameLayout { private int mTouchSlop; private int mMinimumVelocity; private int mMaximumVelocity; - + private int mOverscrollDistance; private int mOverflingDistance; @@ -134,13 +134,13 @@ public class HorizontalScrollView extends FrameLayout { * drags/flings if multiple pointers are used. */ private int mActivePointerId = INVALID_POINTER; - + /** * Sentinel value for no current active pointer. * Used by {@link #mActivePointerId}. */ private static final int INVALID_POINTER = -1; - + public HorizontalScrollView(Context context) { this(context, null); } @@ -279,7 +279,7 @@ public class HorizontalScrollView extends FrameLayout { * * @param fillViewport True to stretch the content's width to the viewport's * boundaries, false otherwise. - * + * * @attr ref android.R.styleable#HorizontalScrollView_fillViewport */ public void setFillViewport(boolean fillViewport) { @@ -322,13 +322,13 @@ public class HorizontalScrollView extends FrameLayout { int width = getMeasuredWidth(); if (child.getMeasuredWidth() < width) { final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); - + int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, mPaddingTop + mPaddingBottom, lp.height); width -= mPaddingLeft; width -= mPaddingRight; int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY); - + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } } @@ -400,7 +400,7 @@ public class HorizontalScrollView extends FrameLayout { } return false; } - + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { /* @@ -453,7 +453,7 @@ public class HorizontalScrollView extends FrameLayout { mIsBeingDragged = false; break; } - + /* * Remember location of down touch. * ACTION_DOWN always refers to pointer index 0. @@ -581,7 +581,7 @@ public class HorizontalScrollView extends FrameLayout { } } } - + mActivePointerId = INVALID_POINTER; mIsBeingDragged = false; @@ -618,7 +618,7 @@ public class HorizontalScrollView extends FrameLayout { } return true; } - + private void onSecondaryPointerUp(MotionEvent ev) { final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; @@ -635,7 +635,7 @@ public class HorizontalScrollView extends FrameLayout { } } } - + @Override protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { @@ -917,7 +917,7 @@ public class HorizontalScrollView extends FrameLayout { if (direction == View.FOCUS_LEFT && getScrollX() < scrollDelta) { scrollDelta = getScrollX(); } else if (direction == View.FOCUS_RIGHT && getChildCount() > 0) { - + int daRight = getChildAt(0).getRight(); int screenRight = getScrollX() + getWidth(); @@ -1033,7 +1033,7 @@ public class HorizontalScrollView extends FrameLayout { if (count == 0) { return contentWidth; } - + int scrollRange = getChildAt(0).getRight(); final int scrollX = mScrollX; final int overscrollRight = Math.max(0, scrollRange - contentWidth); @@ -1045,7 +1045,7 @@ public class HorizontalScrollView extends FrameLayout { return scrollRange; } - + @Override protected int computeHorizontalScrollOffset() { return Math.max(0, super.computeHorizontalScrollOffset()); @@ -1352,25 +1352,25 @@ public class HorizontalScrollView extends FrameLayout { if (getChildCount() > 0) { int width = getWidth() - mPaddingRight - mPaddingLeft; int right = getChildAt(0).getWidth(); - - mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0, + + mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0, Math.max(0, right - width), 0, 0, width/2, 0); - + final boolean movingRight = velocityX > 0; - + View newFocused = findFocusableViewInMyBounds(movingRight, mScroller.getFinalX(), findFocus()); - + if (newFocused == null) { newFocused = this; } - + if (newFocused != findFocus() && newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT)) { mScrollViewMovedFocus = true; mScrollViewMovedFocus = false; } - + invalidate(); } } @@ -1396,11 +1396,12 @@ public class HorizontalScrollView extends FrameLayout { public void setOverScrollMode(int mode) { if (mode != OVER_SCROLL_NEVER) { if (mEdgeGlowLeft == null) { - final Resources res = getContext().getResources(); + Context context = getContext(); + final Resources res = context.getResources(); final Drawable edge = res.getDrawable(R.drawable.overscroll_edge); final Drawable glow = res.getDrawable(R.drawable.overscroll_glow); - mEdgeGlowLeft = new EdgeGlow(edge, glow); - mEdgeGlowRight = new EdgeGlow(edge, glow); + mEdgeGlowLeft = new EdgeGlow(context, edge, glow); + mEdgeGlowRight = new EdgeGlow(context, edge, glow); } } else { mEdgeGlowLeft = null; diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 900c9ec..9fa90dc 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -51,7 +51,7 @@ import java.util.List; * takes care of its own scrolling, so does not require a ScrollView, but * using the two together is possible to achieve the effect of a text view * within a larger container. - * + * * <p>ScrollView only supports vertical scrolling. * * @attr ref android.R.styleable#ScrollView_fillViewport @@ -120,7 +120,7 @@ public class ScrollView extends FrameLayout { private int mTouchSlop; private int mMinimumVelocity; private int mMaximumVelocity; - + private int mOverscrollDistance; private int mOverflingDistance; @@ -269,7 +269,7 @@ public class ScrollView extends FrameLayout { * Indicates whether this ScrollView's content is stretched to fill the viewport. * * @return True if the content fills the viewport, false otherwise. - * + * * @attr ref android.R.styleable#ScrollView_fillViewport */ public boolean isFillViewport() { @@ -282,7 +282,7 @@ public class ScrollView extends FrameLayout { * * @param fillViewport True to stretch the content's height to the viewport's * boundaries, false otherwise. - * + * * @attr ref android.R.styleable#ScrollView_fillViewport */ public void setFillViewport(boolean fillViewport) { @@ -325,14 +325,14 @@ public class ScrollView extends FrameLayout { int height = getMeasuredHeight(); if (child.getMeasuredHeight() < height) { final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); - + int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, mPaddingLeft + mPaddingRight, lp.width); height -= mPaddingTop; height -= mPaddingBottom; int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); - + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } } @@ -521,7 +521,7 @@ public class ScrollView extends FrameLayout { case MotionEvent.ACTION_DOWN: { final float y = ev.getY(); mIsBeingDragged = true; - + /* * If being flinged and user touches, stop the fling. isFinished * will be false if being flinged. @@ -579,7 +579,7 @@ public class ScrollView extends FrameLayout { } } break; - case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_UP: if (mIsBeingDragged) { final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); @@ -615,7 +615,7 @@ public class ScrollView extends FrameLayout { } return true; } - + private void onSecondaryPointerUp(MotionEvent ev) { final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; @@ -632,7 +632,7 @@ public class ScrollView extends FrameLayout { } } } - + @Override protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { @@ -919,9 +919,9 @@ public class ScrollView extends FrameLayout { } else if (direction == View.FOCUS_DOWN) { if (getChildCount() > 0) { int daBottom = getChildAt(0).getBottom(); - + int screenBottom = getScrollY() + getHeight(); - + if (daBottom - screenBottom < maxJump) { scrollDelta = daBottom - screenBottom; } @@ -1038,7 +1038,7 @@ public class ScrollView extends FrameLayout { if (count == 0) { return contentHeight; } - + int scrollRange = getChildAt(0).getBottom(); final int scrollY = mScrollY; final int overscrollBottom = Math.max(0, scrollRange - contentHeight); @@ -1289,7 +1289,7 @@ public class ScrollView extends FrameLayout { } return nextFocus.requestFocus(direction, previouslyFocusedRect); - } + } @Override public boolean requestChildRectangleOnScreen(View child, Rect rectangle, @@ -1325,7 +1325,7 @@ public class ScrollView extends FrameLayout { protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); mIsLayoutDirty = false; - // Give a child focus if it needs it + // Give a child focus if it needs it if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) { scrollToChild(mChildToScrollTo); } @@ -1352,7 +1352,7 @@ public class ScrollView extends FrameLayout { int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect); doScrollY(scrollDelta); } - } + } /** * Return true if child is an descendant of parent, (or equal to the parent). @@ -1364,7 +1364,7 @@ public class ScrollView extends FrameLayout { final ViewParent theParent = child.getParent(); return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent); - } + } /** * Fling the scroll view @@ -1377,18 +1377,18 @@ public class ScrollView extends FrameLayout { if (getChildCount() > 0) { int height = getHeight() - mPaddingBottom - mPaddingTop; int bottom = getChildAt(0).getHeight(); - - mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0, + + mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0, Math.max(0, bottom - height), 0, height/2); - + final boolean movingDown = velocityY > 0; - + View newFocused = findFocusableViewInMyBounds(movingDown, mScroller.getFinalY(), findFocus()); if (newFocused == null) { newFocused = this; } - + if (newFocused != findFocus() && newFocused.requestFocus(movingDown ? View.FOCUS_DOWN : View.FOCUS_UP)) { mScrollViewMovedFocus = true; @@ -1444,11 +1444,12 @@ public class ScrollView extends FrameLayout { public void setOverScrollMode(int mode) { if (mode != OVER_SCROLL_NEVER) { if (mEdgeGlowTop == null) { - final Resources res = getContext().getResources(); + Context context = getContext(); + final Resources res = context.getResources(); final Drawable edge = res.getDrawable(R.drawable.overscroll_edge); final Drawable glow = res.getDrawable(R.drawable.overscroll_glow); - mEdgeGlowTop = new EdgeGlow(edge, glow); - mEdgeGlowBottom = new EdgeGlow(edge, glow); + mEdgeGlowTop = new EdgeGlow(context, edge, glow); + mEdgeGlowBottom = new EdgeGlow(context, edge, glow); } } else { mEdgeGlowTop = null; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 78f3cd9..5e4a514 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -313,6 +313,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Drawable mSelectHandleRight; Drawable mSelectHandleCenter; + private int mLastDownPositionX, mLastDownPositionY; + /* * Kick-start the font cache for the zygote process (to pay the cost of * initializing freetype for our default font only once). @@ -3839,20 +3841,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean changed = false; - SelectionModifierCursorController selectionController = null; - if (mSelectionModifierCursorController != null) { - selectionController = (SelectionModifierCursorController) - mSelectionModifierCursorController; - } - - if (mMovement != null) { /* This code also provides auto-scrolling when a cursor is moved using a * CursorController (insertion point or selection limits). * For selection, ensure start or end is visible depending on controller's state. */ int curs = getSelectionEnd(); - if (selectionController != null && selectionController.isSelectionStartDragged()) { + // Do not create the controller if it is not already created. + if (mSelectionModifierCursorController != null && + mSelectionModifierCursorController.isSelectionStartDragged()) { curs = getSelectionStart(); } @@ -3879,7 +3876,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // - ExtractEditText does not call onFocus when it is displayed. Fixing this issue would // allow to test for hasSelection in onFocusChanged, which would trigger a // startTextSelectionMode here. TODO - if (this instanceof ExtractEditText && selectionController != null && hasSelection()) { + if (this instanceof ExtractEditText && hasSelection() && hasSelectionController()) { startSelectionActionMode(); } @@ -3900,6 +3897,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final ViewTreeObserver observer = getViewTreeObserver(); if (observer != null) { + // No need to create the controller. + // The get method will add the listener on controller creation. if (mInsertionPointCursorController != null) { observer.addOnTouchModeChangeListener(mInsertionPointCursorController); } @@ -3919,6 +3918,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener observer.removeOnPreDrawListener(this); mPreDrawState = PREDRAW_NOT_REGISTERED; } + // No need to create the controller, as getXXController would. if (mInsertionPointCursorController != null) { observer.removeOnTouchModeChangeListener(mInsertionPointCursorController); } @@ -4396,6 +4396,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ protected void updateCursorControllerPositions() { + // No need to create the controllers if they were not already if (mInsertionPointCursorController != null && mInsertionPointCursorController.isShowing()) { mInsertionPointCursorController.updatePosition(); @@ -6906,8 +6907,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener terminateSelectionActionMode(); } + // No need to create the controller if (mSelectionModifierCursorController != null) { - ((SelectionModifierCursorController) mSelectionModifierCursorController).resetTouchOffsets(); + mSelectionModifierCursorController.resetTouchOffsets(); } } @@ -6921,9 +6923,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private int getLastTapPosition() { + // No need to create the controller at that point, no last tap position saved if (mSelectionModifierCursorController != null) { - int lastTapPosition = ((SelectionModifierCursorController) - mSelectionModifierCursorController).getMinTouchOffset(); + int lastTapPosition = mSelectionModifierCursorController.getMinTouchOffset(); if (lastTapPosition >= 0) { // Safety check, should not be possible. if (lastTapPosition > mText.length()) { @@ -7009,8 +7011,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Restore previous selection Selection.setSelection((Spannable)mText, prevStart, prevEnd); - if (hasSelectionController() && !getSelectionController().isShowing()) { - // If the anchors aren't showing, revive them. + if (hasSelectionController()) { + // Revive the anchors. getSelectionController().show(); } return; @@ -7065,6 +7067,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (action == MotionEvent.ACTION_DOWN) { + mLastDownPositionX = (int) event.getX(); + mLastDownPositionY = (int) event.getY(); + // Reset this state; it will be re-set if super.onTouchEvent // causes focus to move to the view. mTouchFocusSelected = false; @@ -7102,6 +7107,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mScrollX != oldScrollX || mScrollY != oldScrollY) { // Hide insertion anchor while scrolling. Leave selection. hideInsertionPointCursorController(); + // No need to create the controller, since there is nothing to update. if (mSelectionModifierCursorController != null && mSelectionModifierCursorController.isShowing()) { mSelectionModifierCursorController.updatePosition(); @@ -7146,7 +7152,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW; } - // TODO Add an extra android:cursorController flag to disable the controller? mInsertionControllerEnabled = windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null && !mTextIsSelectable; mSelectionControllerEnabled = windowSupportsHandles && textCanBeSelected() && @@ -7157,10 +7162,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (!mSelectionControllerEnabled) { - // Stop selection mode if the controller becomes unavailable. - if (mSelectionModifierCursorController != null) { - stopSelectionActionMode(); - } + stopSelectionActionMode(); mSelectionModifierCursorController = null; } } @@ -7565,9 +7567,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private void selectCurrentWord() { - // In case selection mode is started after an orientation change or after a select all, - // use the current selection instead of creating one - if (hasSelection()) { + if (hasPasswordTransformationMethod()) { + // selectCurrentWord is not available on a password field and would return an + // arbitrary 10-charater selection around pressed position. Select all instead. + // Note that cut/copy menu entries are not available for passwords. + // This is however useful to delete or paste to replace the entire content. + Selection.setSelection((Spannable) mText, 0, mText.length()); return; } @@ -7577,11 +7582,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener minOffset = getSelectionStart(); maxOffset = getSelectionEnd(); } else { - // selectionModifierCursorController is not null at that point - SelectionModifierCursorController selectionModifierCursorController = - ((SelectionModifierCursorController) mSelectionModifierCursorController); - minOffset = selectionModifierCursorController.getMinTouchOffset(); - maxOffset = selectionModifierCursorController.getMaxTouchOffset(); + // selectionModifierCursorController is guaranteed to exist at that point + SelectionModifierCursorController selectionController = getSelectionController(); + minOffset = selectionController.getMinTouchOffset(); + maxOffset = selectionController.getMaxTouchOffset(); } int selectionStart, selectionEnd; @@ -7768,7 +7772,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Two spaces at beginning of paste: remove one final int originalLength = mText.length(); ((Editable) mText).replace(min - 1, min, ""); - // Due to filters, there is no garantee that exactly one character was + // Due to filters, there is no guarantee that exactly one character was // removed. Count instead. final int delta = mText.length() - originalLength; min += delta; @@ -7835,6 +7839,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return true; } + if (!isPositionOnText(mLastDownPositionX, mLastDownPositionY) && mInsertionControllerEnabled) { + final int offset = getOffset(mLastDownPositionX, mLastDownPositionY); + Selection.setSelection((Spannable)mText, offset); + if (canPaste()) { + getInsertionController().showWithPaste(); + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } else { + getInsertionController().show(); + } + mEatTouchRelease = true; + return true; + } + if (mSelectionActionMode != null && touchPositionIsInSelection()) { final int start = getSelectionStart(); final int end = getSelectionEnd(); @@ -7871,10 +7888,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Selection.setSelection((Spannable) mText, selectionStart, selectionEnd); } - SelectionModifierCursorController selectionModifierCursorController = - ((SelectionModifierCursorController) mSelectionModifierCursorController); - int minOffset = selectionModifierCursorController.getMinTouchOffset(); - int maxOffset = selectionModifierCursorController.getMaxTouchOffset(); + SelectionModifierCursorController selectionController = getSelectionController(); + int minOffset = selectionController.getMinTouchOffset(); + int maxOffset = selectionController.getMaxTouchOffset(); return ((minOffset >= selectionStart) && (maxOffset < selectionEnd)); } @@ -7886,9 +7902,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * mode is not available. */ private ActionMode.Callback getActionModeCallback() { - // Long press in the current selection. - // Should initiate a drag. Return false, to rely on context menu for now. - if (canSelectText() && !touchPositionIsInSelection()) { + if (canSelectText()) { return new SelectionActionModeCallback(); } return null; @@ -7921,10 +7935,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ private void terminateSelectionActionMode() { stopSelectionActionMode(); + + // No need to create the controller, nothing to cancel in that case. if (mSelectionModifierCursorController != null) { - SelectionModifierCursorController selectionModifierCursorController = - (SelectionModifierCursorController) mSelectionModifierCursorController; - selectionModifierCursorController.cancelFadeOutAnimation(); + mSelectionModifierCursorController.cancelFadeOutAnimation(); } } @@ -7966,7 +7980,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { - if (mSelectionModifierCursorController == null) { + if (!hasSelectionController()) { Log.w(LOG_TAG, "TextView has no selection controller. Action mode cancelled."); return false; } @@ -7983,15 +7997,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean atLeastOne = false; if (canSelectText()) { - if (hasPasswordTransformationMethod()) { - // selectCurrentWord is not available on a password field and would return an - // arbitrary 10-charater selection around pressed position. Select all instead. - // Note that cut/copy menu entries are not available for passwords. - // This is however useful to delete or paste to replace the entire content. - Selection.setSelection((Spannable) mText, 0, mText.length()); - } else { - selectCurrentWord(); - } + selectCurrentWord(); menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll). setAlphabeticShortcut('a'). @@ -8030,7 +8036,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener styledAttributes.recycle(); if (atLeastOne) { - mSelectionModifierCursorController.show(); + getSelectionController().show(); return true; } else { return false; @@ -8049,8 +8055,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (itemId == ID_SELECT_ALL) { Selection.setSelection((Spannable) mText, 0, mText.length()); // Update controller positions after selection change. - if (mSelectionModifierCursorController != null) { - mSelectionModifierCursorController.show(); + if (hasSelectionController()) { + getSelectionController().show(); } return true; } @@ -8094,9 +8100,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void onDestroyActionMode(ActionMode mode) { Selection.setSelection((Spannable) mText, getSelectionStart()); - if (mSelectionModifierCursorController != null) { - mSelectionModifierCursorController.hide(); - } + hideSelectionModifierCursorController(); mSelectionActionMode = null; } } @@ -8254,6 +8258,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mLastParentY; private int mContainerPositionX, mContainerPositionY; private long mTouchTimer; + private boolean mHasPastePopupWindow = false; private PastePopupMenu mPastePopupWindow; public static final int LEFT = 0; @@ -8306,7 +8311,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mDrawable = mSelectHandleCenter; handleWidth = mDrawable.getIntrinsicWidth(); mHotspotX = handleWidth / 2; - mPastePopupWindow = new PastePopupMenu(); + mHasPastePopupWindow = true; break; } } @@ -8474,9 +8479,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mLastParentX = coords[0]; mLastParentY = coords[1]; mIsDragging = true; - if (mPastePopupWindow != null) { + if (mHasPastePopupWindow) { mTouchTimer = SystemClock.uptimeMillis(); - if (mPastePopupWindow.isShowing()) { + if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) { // Tapping on the handle again dismisses the displayed paste view, mPastePopupWindow.hide(); // and makes sure the action up does not display the paste view. @@ -8508,7 +8513,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop(); final int slopSquared = doubleTapSlop * doubleTapSlop; if (distanceSquared < slopSquared) { - mPastePopupWindow.show(); + showPastePopupWindow(); } } } @@ -8542,6 +8547,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener convertFromViewportToContentCoordinates(bounds); moveTo(bounds.left, bounds.top); } + + void showPastePopupWindow() { + if (mHasPastePopupWindow) { + if (mPastePopupWindow == null) { + // Lazy initialisation: create when actually shown only. + mPastePopupWindow = new PastePopupMenu(); + } + mPastePopupWindow.show(); + } + } } private class InsertionPointCursorController implements CursorController { @@ -8566,6 +8581,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener hideDelayed(DELAY_BEFORE_FADE_OUT); } + void showWithPaste() { + show(); + mHandle.showPastePopupWindow(); + } + public void hide() { mHandle.hide(); TextView.this.removeCallbacks(mHider); @@ -8822,12 +8842,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private void hideInsertionPointCursorController() { + // No need to create the controller to hide it. if (mInsertionPointCursorController != null) { mInsertionPointCursorController.hide(); } } private void hideSelectionModifierCursorController() { + // No need to create the controller to hide it. if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.hide(); } @@ -8838,15 +8860,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener hideSelectionModifierCursorController(); } - private int getOffsetForHorizontal(int line, int x) { - x -= getTotalPaddingLeft(); - // Clamp the position to inside of the view. - x = Math.max(0, x); - x = Math.min(getWidth() - getTotalPaddingRight() - 1, x); - x += getScrollX(); - return getLayout().getOffsetForHorizontal(line, x); - } - /** * Get the offset character closest to the specified absolute position. * @@ -8859,15 +8872,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ public int getOffset(int x, int y) { if (getLayout() == null) return -1; - - y -= getTotalPaddingTop(); - // Clamp the position to inside of the view. - y = Math.max(0, y); - y = Math.min(getHeight() - getTotalPaddingBottom() - 1, y); - y += getScrollY(); - - final int line = getLayout().getLineForVertical(y); - final int offset = getOffsetForHorizontal(line, x); + final int line = getLineAtCoordinate(y); + final int offset = getOffsetAtCoordinate(line, x); return offset; } @@ -8875,14 +8881,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final Layout layout = getLayout(); if (layout == null) return -1; - y -= getTotalPaddingTop(); - // Clamp the position to inside of the view. - y = Math.max(0, y); - y = Math.min(getHeight() - getTotalPaddingBottom() - 1, y); - y += getScrollY(); - - int line = getLayout().getLineForVertical(y); - + int line = getLineAtCoordinate(y); final int previousLine = layout.getLineForOffset(previousOffset); final int previousLineTop = layout.getLineTop(previousLine); final int previousLineBottom = layout.getLineBottom(previousLine); @@ -8895,21 +8894,58 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener line = previousLine; } - return getOffsetForHorizontal(line, x); + return getOffsetAtCoordinate(line, x); + } + + private int convertToLocalHorizontalCoordinate(int x) { + x -= getTotalPaddingLeft(); + // Clamp the position to inside of the view. + x = Math.max(0, x); + x = Math.min(getWidth() - getTotalPaddingRight() - 1, x); + x += getScrollX(); + return x; + } + + private int getLineAtCoordinate(int y) { + y -= getTotalPaddingTop(); + // Clamp the position to inside of the view. + y = Math.max(0, y); + y = Math.min(getHeight() - getTotalPaddingBottom() - 1, y); + y += getScrollY(); + return getLayout().getLineForVertical(y); + } + + private int getOffsetAtCoordinate(int line, int x) { + x = convertToLocalHorizontalCoordinate(x); + return getLayout().getOffsetForHorizontal(line, x); + } + + /** Returns true if the screen coordinates position (x,y) corresponds to a character displayed + * in the view. Returns false when the position is in the empty space of left/right of text. + */ + private boolean isPositionOnText(int x, int y) { + if (getLayout() == null) return false; + + final int line = getLineAtCoordinate(y); + x = convertToLocalHorizontalCoordinate(x); + + if (x < getLayout().getLineLeft(line)) return false; + if (x > getLayout().getLineRight(line)) return false; + return true; } @Override public boolean onDragEvent(DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: - return mInsertionPointCursorController != null; + return hasInsertionController(); case DragEvent.ACTION_DRAG_ENTERED: TextView.this.requestFocus(); return true; case DragEvent.ACTION_DRAG_LOCATION: { - final int offset = getOffset((int)event.getX(), (int)event.getY()); + final int offset = getOffset((int) event.getX(), (int) event.getY()); Selection.setSelection((Spannable)mText, offset); return true; } @@ -8952,7 +8988,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mSelectionControllerEnabled; } - CursorController getInsertionController() { + InsertionPointCursorController getInsertionController() { if (!mInsertionControllerEnabled) { return null; } @@ -8969,7 +9005,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mInsertionPointCursorController; } - CursorController getSelectionController() { + SelectionModifierCursorController getSelectionController() { if (!mSelectionControllerEnabled) { return null; } @@ -9028,8 +9064,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mCursorVisible = true; // Cursor Controllers. - private CursorController mInsertionPointCursorController; - private CursorController mSelectionModifierCursorController; + private InsertionPointCursorController mInsertionPointCursorController; + private SelectionModifierCursorController mSelectionModifierCursorController; private ActionMode mSelectionActionMode; private boolean mInsertionControllerEnabled; private boolean mSelectionControllerEnabled; diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 125b210..a2e9486 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -55,6 +55,7 @@ interface IInputMethodManager { void showInputMethodSubtypePickerFromClient(in IInputMethodClient client); void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId); void setInputMethod(in IBinder token, String id); + void setInputMethodAndSubtype(in IBinder token, String id, in InputMethodSubtype subtype); void hideMySoftInput(in IBinder token, int flags); void showMySoftInput(in IBinder token, int flags); void updateStatusIcon(in IBinder token, String packageName, int iconId); diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index c4d6d1b..9a85edc 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -19,7 +19,9 @@ #include <stdio.h> #include "android_util_Binder.h" +#include "android/graphics/GraphicsJNI.h" +#include <binder/IMemory.h> #include <surfaceflinger/SurfaceComposerClient.h> #include <surfaceflinger/Surface.h> #include <ui/Region.h> @@ -91,15 +93,6 @@ struct no_t { static no_t no; -static __attribute__((noinline)) -void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL) -{ - if (!env->ExceptionOccurred()) { - jclass npeClazz = env->FindClass(exc); - env->ThrowNew(npeClazz, msg); - } -} - // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- @@ -444,6 +437,56 @@ static void Surface_unfreezeDisplay( } } +class ScreenshotBitmap : public SkBitmap { +public: + ScreenshotBitmap() { + } + + status_t update(int width, int height) { + status_t res = (width > 0 && height > 0) + ? mScreenshot.update(width, height) + : mScreenshot.update(); + if (res != NO_ERROR) { + return res; + } + + void const* base = mScreenshot.getPixels(); + uint32_t w = mScreenshot.getWidth(); + uint32_t h = mScreenshot.getHeight(); + uint32_t s = mScreenshot.getStride(); + uint32_t f = mScreenshot.getFormat(); + + ssize_t bpr = s * android::bytesPerPixel(f); + setConfig(convertPixelFormat(f), w, h, bpr); + if (f == PIXEL_FORMAT_RGBX_8888) { + setIsOpaque(true); + } + if (w > 0 && h > 0) { + setPixels((void*)base); + } else { + // be safe with an empty bitmap. + setPixels(NULL); + } + + return NO_ERROR; + } + +private: + ScreenshotClient mScreenshot; +}; + +static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height) +{ + ScreenshotBitmap* bitmap = new ScreenshotBitmap(); + + if (bitmap->update(width, height) != NO_ERROR) { + delete bitmap; + return 0; + } + + return GraphicsJNI::createBitmap(env, bitmap, false, NULL); +} + static void Surface_setLayer( JNIEnv* env, jobject clazz, jint zorder) { @@ -669,6 +712,7 @@ static JNINativeMethod gSurfaceMethods[] = { {"setOrientation", "(III)V", (void*)Surface_setOrientation }, {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay }, {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay }, + {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshot }, {"setLayer", "(I)V", (void*)Surface_setLayer }, {"setPosition", "(II)V",(void*)Surface_setPosition }, {"setSize", "(II)V",(void*)Surface_setSize }, diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index 21b810e..d64fb74 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -110,8 +110,8 @@ <color name="background_holo_light">#fff3f3f3</color> <color name="bright_foreground_holo_dark">@android:color/background_holo_light</color> <color name="bright_foreground_holo_light">@android:color/background_holo_dark</color> - <color name="bright_foreground_disabled_holo_dark">#80ffffff</color> - <color name="bright_foreground_disabled_holo_light">#80000000</color> + <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color> + <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color> <color name="bright_foreground_inverse_holo_dark">@android:color/bright_foreground_holo_light</color> <color name="bright_foreground_inverse_holo_light">@android:color/bright_foreground_holo_dark</color> <color name="dim_foreground_holo_dark">#bebebe</color> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 15b5db4..61223b3 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -195,6 +195,10 @@ <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION --> + <!-- If true, the screen can be rotated via the accelerometer in all 4 + rotations as the default behavior. --> + <bool name="config_allowAllRotations">true</bool> + <!-- The number of degrees to rotate the display when the keyboard is open. --> <integer name="config_lidOpenRotation">90</integer> diff --git a/core/tests/coretests/src/android/content/SyncOperationTest.java b/core/tests/coretests/src/android/content/SyncOperationTest.java new file mode 100644 index 0000000..57435e5 --- /dev/null +++ b/core/tests/coretests/src/android/content/SyncOperationTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content; + +import android.accounts.Account; +import android.os.Bundle; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +/** + * You can run those tests with: + * + * adb shell am instrument + * -e debug false + * -w + * -e class android.content.SyncOperationTest com.android.frameworks.coretests/android.test.InstrumentationTestRunner + */ + +public class SyncOperationTest extends AndroidTestCase { + + @SmallTest + public void testToKey() { + Account account1 = new Account("account1", "type1"); + Account account2 = new Account("account2", "type2"); + + Bundle b1 = new Bundle(); + Bundle b2 = new Bundle(); + b2.putBoolean("b2", true); + + SyncOperation op1 = new SyncOperation(account1, + 1, + "authority1", + b1, + 100, + 1000, + 10000); + + // Same as op1 but different time infos + SyncOperation op2 = new SyncOperation(account1, + 1, + "authority1", + b1, + 200, + 2000, + 20000); + + // Same as op1 but different authority + SyncOperation op3 = new SyncOperation(account1, + 1, + "authority2", + b1, + 100, + 1000, + 10000); + + // Same as op1 but different account + SyncOperation op4 = new SyncOperation(account2, + 1, + "authority1", + b1, + 100, + 1000, + 10000); + + // Same as op1 but different bundle + SyncOperation op5 = new SyncOperation(account1, + 1, + "authority1", + b2, + 100, + 1000, + 10000); + + assertEquals(op1.key, op2.key); + assertNotSame(op1.key, op3.key); + assertNotSame(op1.key, op4.key); + assertNotSame(op1.key, op5.key); + } +} diff --git a/core/tests/coretests/src/android/util/TimeUtilsTest.java b/core/tests/coretests/src/android/util/TimeUtilsTest.java index 65a6078..8d9f8e5 100644 --- a/core/tests/coretests/src/android/util/TimeUtilsTest.java +++ b/core/tests/coretests/src/android/util/TimeUtilsTest.java @@ -429,4 +429,22 @@ public class TimeUtilsTest extends TestCase { c.getTimeInMillis(), country); } + + public void testFormatDuration() { + assertFormatDuration("0", 0); + assertFormatDuration("-1ms", -1); + assertFormatDuration("+1ms", 1); + assertFormatDuration("+10ms", 10); + assertFormatDuration("+100ms", 100); + assertFormatDuration("+101ms", 101); + assertFormatDuration("+330ms", 330); + assertFormatDuration("+1s330ms", 1330); + assertFormatDuration("+10s24ms", 10024); + } + + private void assertFormatDuration(String expected, long duration) { + StringBuilder sb = new StringBuilder(); + TimeUtils.formatDuration(duration, sb); + assertEquals("formatDuration(" + duration + ")", expected, sb.toString()); + } } diff --git a/drm/libdrmframework/plugins/widevine/Android.mk b/drm/libdrmframework/plugins/widevine/Android.mk deleted file mode 100644 index 2c388da..0000000 --- a/drm/libdrmframework/plugins/widevine/Android.mk +++ /dev/null @@ -1,27 +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. -# -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := libdrmwvmplugin - -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm/plugins/native - -LOCAL_PRELINK_MODULE := false - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_SHARED_LIBRARY) diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h index 9416ca1..0bfb166 100644 --- a/include/media/IMediaPlayerService.h +++ b/include/media/IMediaPlayerService.h @@ -32,6 +32,7 @@ namespace android { class IMediaRecorder; class IOMX; +struct IStreamSource; class IMediaPlayerService: public IInterface { @@ -45,6 +46,11 @@ public: int audioSessionId = 0) = 0; virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId) = 0; + + virtual sp<IMediaPlayer> create( + pid_t pid, const sp<IMediaPlayerClient> &client, + const sp<IStreamSource> &source, int audioSessionId) = 0; + virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; virtual sp<IOMX> getOMX() = 0; diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h new file mode 100644 index 0000000..6291124 --- /dev/null +++ b/include/media/IStreamSource.h @@ -0,0 +1,66 @@ +/* + * 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_ISTREAMSOURCE_H_ + +#define ANDROID_ISTREAMSOURCE_H_ + +#include <binder/IInterface.h> + +namespace android { + +struct IMemory; +struct IStreamListener; + +struct IStreamSource : public IInterface { + DECLARE_META_INTERFACE(StreamSource); + + virtual void setListener(const sp<IStreamListener> &listener) = 0; + virtual void setBuffers(const Vector<sp<IMemory> > &buffers) = 0; + + virtual void onBufferAvailable(size_t index) = 0; +}; + +struct IStreamListener : public IInterface { + DECLARE_META_INTERFACE(StreamListener); + + enum Command { + FLUSH, + DISCONTINUITY, + EOS + }; + + virtual void queueBuffer(size_t index, size_t size) = 0; + virtual void queueCommand(Command cmd) = 0; +}; + +//////////////////////////////////////////////////////////////////////////////// + +struct BnStreamSource : public BnInterface<IStreamSource> { + virtual status_t onTransact( + uint32_t code, const Parcel &data, Parcel *reply, + uint32_t flags = 0); +}; + +struct BnStreamListener : public BnInterface<IStreamListener> { + virtual status_t onTransact( + uint32_t code, const Parcel &data, Parcel *reply, + uint32_t flags = 0); +}; + +} // namespace android + +#endif // ANDROID_ISTREAMSOURCE_H_ diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 672931e..e7f1d6d 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -106,6 +106,11 @@ public: const KeyedVector<String8, String8> *headers = NULL) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + + virtual status_t setDataSource(const sp<IStreamSource> &source) { + return INVALID_OPERATION; + } + virtual status_t setVideoSurface(const sp<Surface>& surface) = 0; virtual status_t prepare() = 0; virtual status_t prepareAsync() = 0; diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h index 15a3925..d0812de 100644 --- a/include/ui/InputDispatcher.h +++ b/include/ui/InputDispatcher.h @@ -179,8 +179,10 @@ struct InputWindow { TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11, TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12, TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13, - TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14, + TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+14, TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15, + TYPE_DRAG = FIRST_SYSTEM_WINDOW+16, + TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+17, LAST_SYSTEM_WINDOW = 2999, }; diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java index 76c23b7..42eaede 100644 --- a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java +++ b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java @@ -21,7 +21,7 @@ import android.renderscript.*; import android.util.Log; public class BallsRS { - public static final int PART_COUNT = 800; + public static final int PART_COUNT = 1000; public BallsRS() { } diff --git a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs index 96c39b1..47eaf1b 100644 --- a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs +++ b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs @@ -41,7 +41,20 @@ void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint3 fv -= (vec / (len * len * len)) * 20000.f; } else { if (len2 < 0.1) { - continue; + if (xin == x) { + continue; + } + ballOut->delta = 0.f; + ballOut->position = ballIn->position; + if (xin > x) { + ballOut->position.x += 1.f; + } else { + ballOut->position.x -= 1.f; + } + ballOut->color.rgb = 1.f; + ballOut->arcID = -1; + ballOut->arcStr = 0; + return; } // Collision float2 axis = normalize(vec); diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java index 34088fc..0bb83eb 100755 --- a/media/java/android/media/videoeditor/MediaProperties.java +++ b/media/java/android/media/videoeditor/MediaProperties.java @@ -95,6 +95,9 @@ public class MediaProperties { public static final int BITRATE_384K = 384000;
public static final int BITRATE_512K = 512000;
public static final int BITRATE_800K = 800000;
+ public static final int BITRATE_2M = 2000000;
+ public static final int BITRATE_5M = 5000000;
+ public static final int BITRATE_8M = 8000000;
// The array of supported bitrates
private static final int[] SUPPORTED_BITRATES = new int[] {
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 2e5cbe3..731c09d 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -15,6 +15,7 @@ LOCAL_SRC_FILES:= \ IMediaRecorderClient.cpp \ IMediaPlayer.cpp \ IMediaRecorder.cpp \ + IStreamSource.cpp \ Metadata.cpp \ mediarecorder.cpp \ IMediaMetadataRetriever.cpp \ diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index 4abfa75..77199e1 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -23,6 +23,7 @@ #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> #include <media/IOMX.h> +#include <media/IStreamSource.h> #include <utils/Errors.h> // for status_t @@ -31,6 +32,7 @@ namespace android { enum { CREATE_URL = IBinder::FIRST_CALL_TRANSACTION, CREATE_FD, + CREATE_STREAM, DECODE_URL, DECODE_FD, CREATE_MEDIA_RECORDER, @@ -107,6 +109,21 @@ public: return interface_cast<IMediaPlayer>(reply.readStrongBinder());; } + virtual sp<IMediaPlayer> create( + pid_t pid, const sp<IMediaPlayerClient> &client, + const sp<IStreamSource> &source, int audioSessionId) { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(pid)); + data.writeStrongBinder(client->asBinder()); + data.writeStrongBinder(source->asBinder()); + data.writeInt32(static_cast<int32_t>(audioSessionId)); + + remote()->transact(CREATE_STREAM, data, &reply); + + return interface_cast<IMediaPlayer>(reply.readStrongBinder());; + } + virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) { Parcel data, reply; @@ -184,6 +201,27 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(player->asBinder()); return NO_ERROR; } break; + case CREATE_STREAM: + { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + + pid_t pid = static_cast<pid_t>(data.readInt32()); + + sp<IMediaPlayerClient> client = + interface_cast<IMediaPlayerClient>(data.readStrongBinder()); + + sp<IStreamSource> source = + interface_cast<IStreamSource>(data.readStrongBinder()); + + int audioSessionId = static_cast<int>(data.readInt32()); + + sp<IMediaPlayer> player = + create(pid, client, source, audioSessionId); + + reply->writeStrongBinder(player->asBinder()); + return OK; + break; + } case DECODE_URL: { CHECK_INTERFACE(IMediaPlayerService, data, reply); const char* url = data.readCString(); diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp new file mode 100644 index 0000000..89f2b44 --- /dev/null +++ b/media/libmedia/IStreamSource.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "IStreamSource" +#include <utils/Log.h> + +#include <media/IStreamSource.h> + +#include <binder/IMemory.h> +#include <binder/Parcel.h> + +namespace android { + +enum { + // IStreamSource + SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION, + SET_BUFFERS, + ON_BUFFER_AVAILABLE, + + // IStreamListener + QUEUE_BUFFER, + QUEUE_COMMAND, +}; + +struct BpStreamSource : public BpInterface<IStreamSource> { + BpStreamSource(const sp<IBinder> &impl) + : BpInterface<IStreamSource>(impl) { + } + + virtual void setListener(const sp<IStreamListener> &listener) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeStrongBinder(listener->asBinder()); + remote()->transact(SET_LISTENER, data, &reply); + } + + virtual void setBuffers(const Vector<sp<IMemory> > &buffers) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(buffers.size())); + for (size_t i = 0; i < buffers.size(); ++i) { + data.writeStrongBinder(buffers.itemAt(i)->asBinder()); + } + remote()->transact(SET_BUFFERS, data, &reply); + } + + virtual void onBufferAvailable(size_t index) { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(index)); + remote()->transact( + ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(StreamSource, "android.hardware.IStreamSource"); + +status_t BnStreamSource::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { + switch (code) { + case SET_LISTENER: + { + CHECK_INTERFACE(IStreamSource, data, reply); + setListener( + interface_cast<IStreamListener>(data.readStrongBinder())); + break; + } + + case SET_BUFFERS: + { + CHECK_INTERFACE(IStreamSource, data, reply); + size_t n = static_cast<size_t>(data.readInt32()); + Vector<sp<IMemory> > buffers; + for (size_t i = 0; i < n; ++i) { + sp<IMemory> mem = + interface_cast<IMemory>(data.readStrongBinder()); + + buffers.push(mem); + } + setBuffers(buffers); + break; + } + + case ON_BUFFER_AVAILABLE: + { + CHECK_INTERFACE(IStreamSource, data, reply); + onBufferAvailable(static_cast<size_t>(data.readInt32())); + break; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } + + return OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +struct BpStreamListener : public BpInterface<IStreamListener> { + BpStreamListener(const sp<IBinder> &impl) + : BpInterface<IStreamListener>(impl) { + } + + virtual void queueBuffer(size_t index, size_t size) { + Parcel data, reply; + data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(index)); + data.writeInt32(static_cast<int32_t>(size)); + + remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual void queueCommand(Command cmd) { + Parcel data, reply; + data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor()); + data.writeInt32(static_cast<int32_t>(cmd)); + + remote()->transact(QUEUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(StreamListener, "android.hardware.IStreamListener"); + +status_t BnStreamListener::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { + switch (code) { + case QUEUE_BUFFER: + { + CHECK_INTERFACE(IStreamListener, data, reply); + size_t index = static_cast<size_t>(data.readInt32()); + size_t size = static_cast<size_t>(data.readInt32()); + + queueBuffer(index, size); + break; + } + + case QUEUE_COMMAND: + { + CHECK_INTERFACE(IStreamListener, data, reply); + Command cmd = static_cast<Command>(data.readInt32()); + + queueCommand(cmd); + break; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } + + return OK; +} + +} // namespace android diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 00e510b..63d09d6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -278,6 +278,26 @@ sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClie return c; } +sp<IMediaPlayer> MediaPlayerService::create( + pid_t pid, const sp<IMediaPlayerClient> &client, + const sp<IStreamSource> &source, int audioSessionId) { + int32_t connId = android_atomic_inc(&mNextConnId); + sp<Client> c = new Client(this, pid, connId, client, audioSessionId); + + LOGV("Create new client(%d) from pid %d, audioSessionId=%d", + connId, pid, audioSessionId); + + if (OK != c->setDataSource(source)) { + c.clear(); + } else { + wp<Client> w = c; + Mutex::Autolock lock(mLock); + mClients.add(w); + } + + return c; +} + sp<IOMX> MediaPlayerService::getOMX() { Mutex::Autolock autoLock(mLock); @@ -864,6 +884,30 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64 return mStatus; } +status_t MediaPlayerService::Client::setDataSource( + const sp<IStreamSource> &source) { + // create the right type of player + sp<MediaPlayerBase> p = createPlayer(STAGEFRIGHT_PLAYER); + + if (p == NULL) { + return NO_INIT; + } + + if (!p->hardwareOutput()) { + mAudioOutput = new AudioOutput(mAudioSessionId); + static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput); + } + + // now set data source + mStatus = p->setDataSource(source); + + if (mStatus == OK) { + mPlayer = p; + } + + return mStatus; +} + status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface) { LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get()); diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 184324c..62f8ed6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -191,6 +191,11 @@ public: const KeyedVector<String8, String8> *headers, int audioSessionId); virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId); + + virtual sp<IMediaPlayer> create( + pid_t pid, const sp<IMediaPlayerClient> &client, + const sp<IStreamSource> &source, int audioSessionId); + virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); virtual sp<IOMX> getOMX(); @@ -234,6 +239,9 @@ private: const KeyedVector<String8, String8> *headers); status_t setDataSource(int fd, int64_t offset, int64_t length); + + status_t setDataSource(const sp<IStreamSource> &source); + static void notify(void* cookie, int msg, int ext1, int ext2); pid_t pid() const { return mPid; } diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index 58ef99b..da564dc 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -44,6 +44,10 @@ status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length return mPlayer->setDataSource(dup(fd), offset, length); } +status_t StagefrightPlayer::setDataSource(const sp<IStreamSource> &source) { + return mPlayer->setDataSource(source); +} + status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) { LOGV("setVideoSurface"); diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index c4a2588..fc72bfb 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -35,6 +35,9 @@ public: const char *url, const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + + virtual status_t setDataSource(const sp<IStreamSource> &source); + virtual status_t setVideoSurface(const sp<Surface> &surface); virtual status_t prepare(); virtual status_t prepareAsync(); diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index ec58919..a804866 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -34,13 +34,16 @@ #include "UDPPusher.h" #include <binder/IPCThreadState.h> +#include <binder/MemoryDealer.h> +#include <media/IStreamSource.h> +#include <media/stagefright/foundation/hexdump.h> +#include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/AudioPlayer.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/FileSource.h> #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaExtractor.h> -#include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXCodec.h> @@ -155,6 +158,201 @@ private: const AwesomeNativeWindowRenderer &); }; +//////////////////////////////////////////////////////////////////////////////// + +struct QueueDataSource; + +struct QueueListener : public BnStreamListener { + QueueListener(QueueDataSource *owner) + : mOwner(owner) { + } + + void clearOwner(); + + virtual void queueBuffer(size_t index, size_t size); + virtual void queueCommand(Command cmd); + +private: + Mutex mLock; + + QueueDataSource *mOwner; + + DISALLOW_EVIL_CONSTRUCTORS(QueueListener); +}; + +struct QueueDataSource : public DataSource { + QueueDataSource(const sp<IStreamSource> &source); + + virtual status_t initCheck() const; + + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + + virtual void queueBuffer(size_t index, size_t size); + virtual void queueCommand(IStreamListener::Command cmd); + +protected: + virtual ~QueueDataSource(); + +private: + enum { + kNumBuffers = 16 + }; + + struct BufferInfo { + size_t mIndex; + size_t mOffset; + size_t mSize; + }; + + Mutex mLock; + Condition mCondition; + + sp<IStreamSource> mSource; + sp<QueueListener> mListener; + sp<MemoryDealer> mDealer; + Vector<sp<IMemory> > mBuffers; + + List<BufferInfo> mFilledBuffers; + + off64_t mPosition; + bool mEOS; + + DISALLOW_EVIL_CONSTRUCTORS(QueueDataSource); +}; + +QueueDataSource::QueueDataSource(const sp<IStreamSource> &source) + : mSource(source), + mPosition(0), + mEOS(false) { + mListener = new QueueListener(this); + mSource->setListener(mListener); + + static const size_t kBufferSize = 8192; + + mDealer = new MemoryDealer(kNumBuffers * kBufferSize); + for (size_t i = 0; i < kNumBuffers; ++i) { + sp<IMemory> mem = mDealer->allocate(kBufferSize); + CHECK(mem != NULL); + + mBuffers.push(mem); + } + mSource->setBuffers(mBuffers); + + for (size_t i = 0; i < kNumBuffers; ++i) { + mSource->onBufferAvailable(i); + } +} + +QueueDataSource::~QueueDataSource() { + Mutex::Autolock autoLock(mLock); + + while (mFilledBuffers.size() < kNumBuffers && !mEOS) { + mCondition.wait(mLock); + } + + mListener->clearOwner(); +} + +status_t QueueDataSource::initCheck() const { + return OK; +} + +ssize_t QueueDataSource::readAt(off64_t offset, void *data, size_t size) { + if (offset != mPosition) { + return -EPIPE; + } + + Mutex::Autolock autoLock(mLock); + + size_t sizeDone = 0; + + while (sizeDone < size) { + while (mFilledBuffers.empty() && !mEOS) { + mCondition.wait(mLock); + } + + if (mFilledBuffers.empty()) { + if (sizeDone > 0) { + mPosition += sizeDone; + return sizeDone; + } + return ERROR_END_OF_STREAM; + } + + BufferInfo &info = *mFilledBuffers.begin(); + + size_t copy = size - sizeDone; + if (copy > info.mSize) { + copy = info.mSize; + } + + memcpy((uint8_t *)data + sizeDone, + (const uint8_t *)mBuffers.itemAt(info.mIndex)->pointer() + + info.mOffset, + copy); + + info.mSize -= copy; + info.mOffset += copy; + sizeDone += copy; + + if (info.mSize == 0) { + mSource->onBufferAvailable(info.mIndex); + mFilledBuffers.erase(mFilledBuffers.begin()); + } + } + + mPosition += sizeDone; + + return sizeDone; +} + +void QueueDataSource::queueBuffer(size_t index, size_t size) { + Mutex::Autolock autoLock(mLock); + + CHECK_LT(index, mBuffers.size()); + CHECK_LE(size, mBuffers.itemAt(index)->size()); + + BufferInfo info; + info.mIndex = index; + info.mSize = size; + info.mOffset = 0; + + mFilledBuffers.push_back(info); + mCondition.signal(); +} + +void QueueDataSource::queueCommand(IStreamListener::Command cmd) { + Mutex::Autolock autoLock(mLock); + + if (cmd == IStreamListener::EOS) { + mEOS = true; + mCondition.signal(); + } +} + +void QueueListener::clearOwner() { + Mutex::Autolock autoLock(mLock); + mOwner = NULL; +} + +void QueueListener::queueBuffer(size_t index, size_t size) { + Mutex::Autolock autoLock(mLock); + if (mOwner == NULL) { + return; + } + mOwner->queueBuffer(index, size); +} + +void QueueListener::queueCommand(Command cmd) { + Mutex::Autolock autoLock(mLock); + if (mOwner == NULL) { + return; + } + mOwner->queueCommand(cmd); +} + +//////////////////////////////////////////////////////////////////////////////// + AwesomePlayer::AwesomePlayer() : mQueueStarted(false), mTimeSource(NULL), @@ -164,7 +362,7 @@ AwesomePlayer::AwesomePlayer() mExtractorFlags(0), mVideoBuffer(NULL), mDecryptHandle(NULL) { - CHECK_EQ(mClient.connect(), OK); + CHECK_EQ(mClient.connect(), (status_t)OK); DataSource::RegisterDefaultSniffers(); @@ -264,6 +462,26 @@ status_t AwesomePlayer::setDataSource( return setDataSource_l(dataSource); } +status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) { + Mutex::Autolock autoLock(mLock); + + reset_l(); + + sp<DataSource> dataSource = new QueueDataSource(source); + +#if 0 + sp<MediaExtractor> extractor = + MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); + + return setDataSource_l(extractor); +#else + sp<NuCachedSource2> cached = new NuCachedSource2(dataSource); + dataSource = cached; + + return setDataSource_l(dataSource); +#endif +} + status_t AwesomePlayer::setDataSource_l( const sp<DataSource> &dataSource) { sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); @@ -619,7 +837,8 @@ void AwesomePlayer::partial_reset_l() { IPCThreadState::self()->flushCommands(); } - CHECK_EQ(OK, initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData)); + CHECK_EQ((status_t)OK, + initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData)); } void AwesomePlayer::onStreamDone() { @@ -1171,7 +1390,7 @@ void AwesomePlayer::onVideoEvent() { options.clearSeekTo(); if (err != OK) { - CHECK_EQ(mVideoBuffer, NULL); + CHECK(mVideoBuffer == NULL); if (err == INFO_FORMAT_CHANGED) { LOGV("VideoSource signalled format change."); diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index e33f467..46f4a35 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -67,6 +67,8 @@ struct AwesomePlayer { status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setDataSource(const sp<IStreamSource> &source); + void reset(); status_t prepare(); diff --git a/media/libwvm/Android.mk b/media/libwvm/Android.mk deleted file mode 100644 index 7c75c0f..0000000 --- a/media/libwvm/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -# create an empty mk for libwvm -# for integration purpose -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := libwvm - -LOCAL_MODULE_TAGS := optional -include $(BUILD_SHARED_LIBRARY) diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png Binary files differnew file mode 100644 index 0000000..d083396 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_veto.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_veto.png Binary files differnew file mode 100644 index 0000000..395604f --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_veto.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png Binary files differnew file mode 100644 index 0000000..51b5809 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png Binary files differnew file mode 100644 index 0000000..37ef7e1 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png Binary files differnew file mode 100644 index 0000000..d9b4eca --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png Binary files differnew file mode 100644 index 0000000..c091489 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png Binary files differnew file mode 100644 index 0000000..73a9897 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png Binary files differnew file mode 100644 index 0000000..7cb2643 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png diff --git a/packages/SystemUI/res/drawable-hdpi/recent_overlay.png b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png Binary files differnew file mode 100644 index 0000000..fcf4417 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png diff --git a/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png Binary files differnew file mode 100644 index 0000000..af36ac7 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png diff --git a/packages/SystemUI/res/drawable-hdpi/sysbar_signalmini_100.png b/packages/SystemUI/res/drawable-hdpi/sysbar_signalmini_100.png Binary files differnew file mode 100644 index 0000000..d89f889 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/sysbar_signalmini_100.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_veto.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_veto.png Binary files differnew file mode 100644 index 0000000..f6299e9 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_veto.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png Binary files differnew file mode 100644 index 0000000..fe44063 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png Binary files differnew file mode 100644 index 0000000..8088a2f --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png Binary files differnew file mode 100644 index 0000000..96bf2ec --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png Binary files differnew file mode 100644 index 0000000..cc56778 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png diff --git a/packages/SystemUI/res/drawable/recent_overlay.png b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png Binary files differindex 4dfa3d9..4dfa3d9 100644 --- a/packages/SystemUI/res/drawable/recent_overlay.png +++ b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png diff --git a/packages/SystemUI/res/drawable/recent_rez_border.png b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png Binary files differindex ad025f5..ad025f5 100644 --- a/packages/SystemUI/res/drawable/recent_rez_border.png +++ b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_0.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_0.png Binary files differnew file mode 100644 index 0000000..7371571 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_10.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_10.png Binary files differnew file mode 100644 index 0000000..5781e9a --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_10.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_100.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_100.png Binary files differnew file mode 100644 index 0000000..c65728c --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_100.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_20.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_20.png Binary files differnew file mode 100644 index 0000000..a249fa2 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_20.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_30.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_30.png Binary files differnew file mode 100644 index 0000000..289c088 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_30.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_40.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_40.png Binary files differnew file mode 100644 index 0000000..f49dbd6 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_40.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_50.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_50.png Binary files differnew file mode 100644 index 0000000..2f83e68 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_50.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_60.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_60.png Binary files differnew file mode 100644 index 0000000..bedc021 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_60.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_70.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_70.png Binary files differnew file mode 100644 index 0000000..edd8c05 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_70.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_80.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_80.png Binary files differnew file mode 100644 index 0000000..148e20c --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_80.png diff --git a/packages/SystemUI/res/drawable-mdpi/sysbar_signal_90.png b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_90.png Binary files differnew file mode 100644 index 0000000..5a90ccb --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/sysbar_signal_90.png diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png Binary files differnew file mode 100644 index 0000000..aedf7e7 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml index 5fa8b3b..fb4cf3f 100644 --- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml +++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml @@ -20,9 +20,8 @@ android:layout_height="match_parent" android:layout_width="match_parent" android:animateLayoutChanges="true" - android:background="@drawable/bg_scrim_notification" android:paddingTop="32dp" - android:paddingBottom="32dp" + android:paddingBottom="@dimen/status_bar_panel_bottom_offset" android:orientation="vertical" android:gravity="right" > @@ -66,6 +65,7 @@ android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_below="@id/clock" + android:layout_marginTop="4dp" android:layout_marginRight="48dp" android:gravity="right" /> @@ -76,9 +76,10 @@ android:layout_width="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@id/date" - android:layout_marginTop="16dp" android:layout_marginLeft="48dp" - android:baseline="17dp" + android:layout_marginTop="18dp" + android:layout_marginRight="8dp" + android:baseline="15dp" /> <TextView @@ -97,7 +98,8 @@ android:layout_width="wrap_content" android:layout_toRightOf="@id/battery_text" android:layout_alignBaseline="@id/battery" - android:baseline="21dp" + android:layout_marginRight="8dp" + android:baseline="15dp" /> <TextView @@ -114,11 +116,11 @@ android:id="@+id/settings_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentRight="true" android:layout_alignBaseline="@id/battery" + android:layout_alignParentRight="true" android:paddingRight="16dp" android:src="@drawable/ic_notification_open" - android:baseline="17dp" + android:baseline="21dp" /> <ImageView @@ -130,7 +132,7 @@ android:paddingRight="16dp" android:visibility="invisible" android:src="@drawable/status_bar_veto" - android:baseline="17dp" + android:baseline="21dp" /> </com.android.systemui.statusbar.tablet.NotificationTitleArea> diff --git a/packages/SystemUI/res/values-xlarge/dimens.xml b/packages/SystemUI/res/values-xlarge/dimens.xml index 009b7a8..5ae3982 100644 --- a/packages/SystemUI/res/values-xlarge/dimens.xml +++ b/packages/SystemUI/res/values-xlarge/dimens.xml @@ -22,6 +22,8 @@ <dimen name="notification_large_icon_height">60dp</dimen> <!-- The width of the ticker, including the icon --> <dimen name="notification_ticker_width">360dp</dimen> + <!-- Status bar panel bottom offset (height of status bar - overlap) --> + <dimen name="status_bar_panel_bottom_offset">36dp</dimen> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 2dad81c..915fa2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -294,7 +294,7 @@ public class PhoneStatusBar extends StatusBar { WindowManager.LayoutParams lp = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, - WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, + WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL @@ -1254,7 +1254,7 @@ public class PhoneStatusBar extends StatusBar { lp = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, + WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, @@ -1282,7 +1282,7 @@ public class PhoneStatusBar extends StatusBar { lp.height = getExpandedHeight(); lp.x = 0; mTrackingPosition = lp.y = -disph; // sufficiently large negative - lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; + lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java index 7f743b2..b05fe1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java @@ -163,6 +163,7 @@ public class TabletTicker extends Handler { WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT); lp.gravity = Gravity.BOTTOM | Gravity.RIGHT; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 1c1a46e..f892e9e 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -103,6 +103,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR; import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; +import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; @@ -148,31 +149,32 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int APPLICATION_LAYER = 2; static final int PHONE_LAYER = 3; static final int SEARCH_BAR_LAYER = 4; - static final int STATUS_BAR_PANEL_LAYER = 5; + static final int STATUS_BAR_SUB_PANEL_LAYER = 5; static final int SYSTEM_DIALOG_LAYER = 6; // toasts and the plugged-in battery thing static final int TOAST_LAYER = 7; static final int STATUS_BAR_LAYER = 8; + static final int STATUS_BAR_PANEL_LAYER = 9; // SIM errors and unlock. Not sure if this really should be in a high layer. - static final int PRIORITY_PHONE_LAYER = 9; + static final int PRIORITY_PHONE_LAYER = 10; // like the ANR / app crashed dialogs - static final int SYSTEM_ALERT_LAYER = 10; + static final int SYSTEM_ALERT_LAYER = 11; // system-level error dialogs - static final int SYSTEM_ERROR_LAYER = 11; + static final int SYSTEM_ERROR_LAYER = 12; // on-screen keyboards and other such input method user interfaces go here. - static final int INPUT_METHOD_LAYER = 12; + static final int INPUT_METHOD_LAYER = 13; // on-screen keyboards and other such input method user interfaces go here. - static final int INPUT_METHOD_DIALOG_LAYER = 13; + static final int INPUT_METHOD_DIALOG_LAYER = 14; // the keyguard; nothing on top of these can take focus, since they are // responsible for power management when displayed. - static final int KEYGUARD_LAYER = 14; - static final int KEYGUARD_DIALOG_LAYER = 15; + static final int KEYGUARD_LAYER = 15; + static final int KEYGUARD_DIALOG_LAYER = 16; // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows - static final int DRAG_LAYER = 16; + static final int DRAG_LAYER = 17; // things in here CAN NOT take focus, but are shown on top of everything else. - static final int SYSTEM_OVERLAY_LAYER = 17; - static final int SECURE_SYSTEM_OVERLAY_LAYER = 18; + static final int SYSTEM_OVERLAY_LAYER = 18; + static final int SECURE_SYSTEM_OVERLAY_LAYER = 19; static final int APPLICATION_MEDIA_SUBLAYER = -2; static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; @@ -239,6 +241,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; int mUserRotation = Surface.ROTATION_0; + boolean mAllowAllRotations; boolean mCarDockEnablesAccelerometer; boolean mDeskDockEnablesAccelerometer; int mLidKeyboardAccessibility; @@ -274,10 +277,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + // The current size of the screen; really; (ir)regardless of whether the status + // bar can be hidden or not + int mUnrestrictedScreenLeft, mUnrestrictedScreenTop; + int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight; // The current size of the screen; these may be different than (0,0)-(dw,dh) // if the status bar can't be hidden; in that case it effectively carves out // that area of the display from all other windows. - int mScreenLeft, mScreenTop, mScreenWidth, mScreenHeight; + int mRestrictedScreenLeft, mRestrictedScreenTop; + int mRestrictedScreenWidth, mRestrictedScreenHeight; // During layout, the current screen borders with all outer decoration // (status bar, input method dock) accounted for. int mCurLeft, mCurTop, mCurRight, mCurBottom; @@ -650,6 +658,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.integer.config_carDockRotation); mDeskDockRotation = readRotation( com.android.internal.R.integer.config_deskDockRotation); + mAllowAllRotations = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowAllRotations); mCarDockEnablesAccelerometer = mContext.getResources().getBoolean( com.android.internal.R.bool.config_carDockEnablesAccelerometer); mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean( @@ -906,6 +916,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { return STATUS_BAR_LAYER; case TYPE_STATUS_BAR_PANEL: return STATUS_BAR_PANEL_LAYER; + case TYPE_STATUS_BAR_SUB_PANEL: + return STATUS_BAR_SUB_PANEL_LAYER; case TYPE_SYSTEM_DIALOG: return SYSTEM_DIALOG_LAYER; case TYPE_SEARCH_BAR: @@ -1126,6 +1138,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { "PhoneWindowManager"); mStatusBarPanels.add(win); break; + case TYPE_STATUS_BAR_SUB_PANEL: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.STATUS_BAR_SERVICE, + "PhoneWindowManager"); + mStatusBarPanels.add(win); + break; case TYPE_KEYGUARD: if (mKeyguard != null) { return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; @@ -1401,8 +1419,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { contentInset.set(mCurLeft, mCurTop, - (mScreenLeft+mScreenWidth) - mCurRight, - (mScreenTop+mScreenHeight) - mCurBottom); + (mRestrictedScreenLeft+mRestrictedScreenWidth) - mCurRight, + (mRestrictedScreenTop+mRestrictedScreenHeight) - mCurBottom); } else { contentInset.setEmpty(); } @@ -1410,9 +1428,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void beginLayoutLw(int displayWidth, int displayHeight) { - mScreenLeft = mScreenTop = 0; - mScreenWidth = displayWidth; - mScreenHeight = displayHeight; + mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0; + mUnrestrictedScreenWidth = displayWidth; + mUnrestrictedScreenHeight = displayHeight; + mRestrictedScreenLeft = mRestrictedScreenTop = 0; + mRestrictedScreenWidth = displayWidth; + mRestrictedScreenHeight = displayHeight; mDockLeft = mContentLeft = mCurLeft = 0; mDockTop = mContentTop = mCurTop = 0; mDockRight = mContentRight = mCurRight = displayWidth; @@ -1451,16 +1472,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else { // Status bar can't go away; the part of the screen it // covers does not exist for anything behind it. - if (mScreenTop == r.top) { - mScreenTop = r.bottom; - mScreenHeight -= (r.bottom-r.top); - } else if ((mScreenHeight-mScreenTop) == r.bottom) { - mScreenHeight -= (r.bottom-r.top); + if (mRestrictedScreenTop == r.top) { + mRestrictedScreenTop = r.bottom; + mRestrictedScreenHeight -= (r.bottom-r.top); + } else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) { + mRestrictedScreenHeight -= (r.bottom-r.top); } - mContentTop = mCurTop = mDockTop = mScreenTop; - mContentBottom = mCurBottom = mDockBottom = mScreenTop+mScreenHeight; - if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mScreenTop=" + mScreenTop - + " mScreenHeight=" + mScreenHeight); + mContentTop = mCurTop = mDockTop = mRestrictedScreenTop; + mContentBottom = mCurBottom = mDockBottom + = mRestrictedScreenTop + mRestrictedScreenHeight; + if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mRestrictedScreenTop=" + + mRestrictedScreenTop + + " mRestrictedScreenHeight=" + mRestrictedScreenHeight); } } } @@ -1552,10 +1575,21 @@ public class PhoneWindowManager implements WindowManagerPolicy { // frame is the same as the one we are attached to. setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf); } else { - pf.left = df.left = mScreenLeft; - pf.top = df.top = mScreenTop; - pf.right = df.right = mScreenLeft+mScreenWidth; - pf.bottom = df.bottom = mScreenTop+mScreenHeight; + if (attrs.type == TYPE_STATUS_BAR_PANEL) { + // Status bar panels are the only windows who can go on top of + // the status bar. They are protected by the STATUS_BAR_SERVICE + // permission, so they have the same privileges as the status + // bar itself. + pf.left = df.left = mUnrestrictedScreenLeft; + pf.top = df.top = mUnrestrictedScreenTop; + pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; + pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; + } else { + pf.left = df.left = mRestrictedScreenLeft; + pf.top = df.top = mRestrictedScreenTop; + pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth; + pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight; + } if (adjust != SOFT_INPUT_ADJUST_RESIZE) { cf.left = mDockLeft; cf.top = mDockTop; @@ -1579,10 +1613,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) { // A window that has requested to fill the entire screen just // gets everything, period. - pf.left = df.left = cf.left = mScreenLeft; - pf.top = df.top = cf.top = mScreenTop; - pf.right = df.right = cf.right = mScreenLeft+mScreenWidth; - pf.bottom = df.bottom = cf.bottom = mScreenTop+mScreenHeight; + if (attrs.type == TYPE_STATUS_BAR_PANEL) { + pf.left = df.left = cf.left = mUnrestrictedScreenLeft; + pf.top = df.top = cf.top = mUnrestrictedScreenTop; + pf.right = df.right = cf.right + = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; + pf.bottom = df.bottom = cf.bottom + = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; + } else { + pf.left = df.left = cf.left = mRestrictedScreenLeft; + pf.top = df.top = cf.top = mRestrictedScreenTop; + pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth; + pf.bottom = df.bottom = cf.bottom + = mRestrictedScreenTop+mRestrictedScreenHeight; + } if (adjust != SOFT_INPUT_ADJUST_NOTHING) { vf.left = mCurLeft; vf.top = mCurTop; @@ -1841,9 +1885,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { rect.union(w.getShownFrameLw()); } } - final int insetw = mScreenWidth/10; - final int inseth = mScreenHeight/10; - if (rect.contains(insetw, inseth, mScreenWidth-insetw, mScreenHeight-inseth)) { + final int insetw = mRestrictedScreenWidth/10; + final int inseth = mRestrictedScreenHeight/10; + if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw, + mRestrictedScreenHeight-inseth)) { // All of the status bar windows put together cover the // screen, so the app can't be seen. (Note this test doesn't // work if the rects of these windows are at off offsets or @@ -2302,7 +2347,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return getCurrentPortraitRotation(lastRotation); } - mOrientationListener.setAllow180Rotation( + mOrientationListener.setAllow180Rotation(mAllowAllRotations || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // case for nosensor meaning ignore sensor and consider only lid diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp index 995e31c..aee01ab 100644 --- a/services/audioflinger/A2dpAudioInterface.cpp +++ b/services/audioflinger/A2dpAudioInterface.cpp @@ -23,10 +23,13 @@ #include "A2dpAudioInterface.h" #include "audio/liba2dp.h" - +#include <hardware_legacy/power.h> namespace android { +static const char *sA2dpWakeLock = "A2dpOutputStream"; +#define MAX_WRITE_RETRIES 5 + // ---------------------------------------------------------------------------- //AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface() @@ -263,44 +266,55 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set( A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut() { LOGV("A2dpAudioStreamOut destructor"); - standby(); close(); LOGV("A2dpAudioStreamOut destructor returning from close()"); } ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes) { - Mutex::Autolock lock(mLock); - - size_t remaining = bytes; status_t status = -1; + { + Mutex::Autolock lock(mLock); - if (!mBluetoothEnabled || mClosing || mSuspended) { - LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \ - mBluetoothEnabled %d, mClosing %d, mSuspended %d", - mBluetoothEnabled, mClosing, mSuspended); - goto Error; - } - - status = init(); - if (status < 0) - goto Error; + size_t remaining = bytes; - while (remaining > 0) { - status = a2dp_write(mData, buffer, remaining); - if (status <= 0) { - LOGE("a2dp_write failed err: %d\n", status); + if (!mBluetoothEnabled || mClosing || mSuspended) { + LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \ + mBluetoothEnabled %d, mClosing %d, mSuspended %d", + mBluetoothEnabled, mClosing, mSuspended); goto Error; } - remaining -= status; - buffer = ((char *)buffer) + status; - } - mStandby = false; + if (mStandby) { + acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock); + mStandby = false; + } + + status = init(); + if (status < 0) + goto Error; + + int retries = MAX_WRITE_RETRIES; + while (remaining > 0 && retries) { + status = a2dp_write(mData, buffer, remaining); + if (status < 0) { + LOGE("a2dp_write failed err: %d\n", status); + goto Error; + } + if (status == 0) { + retries--; + } + remaining -= status; + buffer = (char *)buffer + status; + } - return bytes; + return bytes; + } Error: + + standby(); + // Simulate audio output timing in case of error usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000); @@ -324,19 +338,22 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::init() status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() { - int result = 0; - - if (mClosing) { - LOGV("Ignore standby, closing"); - return result; - } - Mutex::Autolock lock(mLock); + return standby_l(); +} + +status_t A2dpAudioInterface::A2dpAudioStreamOut::standby_l() +{ + int result = NO_ERROR; if (!mStandby) { - result = a2dp_stop(mData); - if (result == 0) - mStandby = true; + LOGV_IF(mClosing || !mBluetoothEnabled, "Standby skip stop: closing %d enabled %d", + mClosing, mBluetoothEnabled); + if (!mClosing && mBluetoothEnabled) { + result = a2dp_stop(mData); + } + release_wake_lock(sA2dpWakeLock); + mStandby = true; } return result; @@ -362,6 +379,9 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& ke key = String8("closing"); if (param.get(key, value) == NO_ERROR) { mClosing = (value == "true"); + if (mClosing) { + standby(); + } param.remove(key); } key = AudioParameter::keyRouting; @@ -444,6 +464,7 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::close() status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l() { + standby_l(); if (mData) { LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)"); a2dp_cleanup(mData); diff --git a/services/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h index 48154f9..cef1926 100644 --- a/services/audioflinger/A2dpAudioInterface.h +++ b/services/audioflinger/A2dpAudioInterface.h @@ -103,6 +103,7 @@ private: status_t setAddress(const char* address); status_t setBluetoothEnabled(bool enabled); status_t setSuspended(bool onOff); + status_t standby_l(); private: int mFd; diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index eca37b7..723432d 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1300,7 +1300,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } public void setInputMethod(IBinder token, String id) { - setInputMethodWithSubtype(token, id, NOT_A_SUBTYPE_ID); + setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID); + } + + public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) { + synchronized (mMethodMap) { + if (subtype != null) { + setInputMethodWithSubtypeId(token, id, getSubtypeIdFromHashCode( + mMethodMap.get(id), subtype.hashCode())); + } else { + setInputMethod(token, id); + } + } } public boolean switchToLastInputMethod(IBinder token) { @@ -1309,7 +1320,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (lastIme != null) { InputMethodInfo imi = mMethodMap.get(lastIme.first); if (imi != null) { - setInputMethodWithSubtype(token, lastIme.first, getSubtypeIdFromHashCode( + setInputMethodWithSubtypeId(token, lastIme.first, getSubtypeIdFromHashCode( imi, Integer.valueOf(lastIme.second))); return true; } @@ -1318,7 +1329,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - private void setInputMethodWithSubtype(IBinder token, String id, int subtypeId) { + private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) { synchronized (mMethodMap) { if (token == null) { if (mContext.checkCallingOrSelfPermission( @@ -1909,11 +1920,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } private int getSubtypeIdFromHashCode(InputMethodInfo imi, int subtypeHashCode) { - ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes(); - for (int i = 0; i < subtypes.size(); ++i) { - InputMethodSubtype ims = subtypes.get(i); - if (subtypeHashCode == ims.hashCode()) { - return i; + if (imi != null) { + ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes(); + for (int i = 0; i < subtypes.size(); ++i) { + InputMethodSubtype ims = subtypes.get(i); + if (subtypeHashCode == ims.hashCode()) { + return i; + } } } return NOT_A_SUBTYPE_ID; diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java new file mode 100644 index 0000000..299567a --- /dev/null +++ b/services/java/com/android/server/ScreenRotationAnimation.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; // TODO: use com.android.server.wm, once things move there + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.util.DisplayMetrics; +import android.util.Slog; +import android.view.Display; +import android.view.Surface; +import android.view.SurfaceSession; + +class ScreenRotationAnimation { + private static final String TAG = "ScreenRotationAnimation"; + + Surface mSurface; + int mWidth, mHeight; + + int mBaseRotation; + int mCurRotation; + int mDeltaRotation; + + final Matrix mMatrix = new Matrix(); + final float[] mTmpFloats = new float[9]; + + public ScreenRotationAnimation(Display display, SurfaceSession session) { + final DisplayMetrics dm = new DisplayMetrics(); + display.getMetrics(dm); + + Bitmap screenshot = Surface.screenshot(0, 0); + + if (screenshot != null) { + // Screenshot does NOT include rotation! + mBaseRotation = 0; + mWidth = screenshot.getWidth(); + mHeight = screenshot.getHeight(); + } else { + // Just in case. + mBaseRotation = display.getRotation(); + mWidth = dm.widthPixels; + mHeight = dm.heightPixels; + } + + Surface.openTransaction(); + if (mSurface != null) { + mSurface.destroy(); + mSurface = null; + } + try { + mSurface = new Surface(session, 0, "FreezeSurface", + -1, mWidth, mHeight, PixelFormat.OPAQUE, 0); + } catch (Surface.OutOfResourcesException e) { + Slog.w(TAG, "Unable to allocate freeze surface", e); + } + mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 200); + setRotation(display.getRotation()); + + Rect dirty = new Rect(0, 0, mWidth, mHeight); + Canvas c = null; + try { + c = mSurface.lockCanvas(dirty); + } catch (IllegalArgumentException e) { + Slog.w(TAG, "Unable to lock surface", e); + return; + } catch (Surface.OutOfResourcesException e) { + Slog.w(TAG, "Unable to lock surface", e); + return; + } + if (c == null) { + Slog.w(TAG, "Null surface"); + return; + } + + if (screenshot != null) { + c.drawBitmap(screenshot, 0, 0, new Paint(0)); + } else { + c.drawColor(Color.GREEN); + } + + mSurface.unlockCanvasAndPost(c); + Surface.closeTransaction(); + + screenshot.recycle(); + } + + // Must be called while in a transaction. + public void setRotation(int rotation) { + mCurRotation = rotation; + int delta = mCurRotation - mBaseRotation; + if (delta < 0) delta += 4; + mDeltaRotation = delta; + + switch (delta) { + case Surface.ROTATION_0: + mMatrix.reset(); + break; + case Surface.ROTATION_90: + mMatrix.setRotate(90, 0, 0); + mMatrix.postTranslate(0, mWidth); + break; + case Surface.ROTATION_180: + mMatrix.setRotate(180, 0, 0); + mMatrix.postTranslate(mWidth, mHeight); + break; + case Surface.ROTATION_270: + mMatrix.setRotate(270, 0, 0); + mMatrix.postTranslate(mHeight, 0); + break; + } + + mMatrix.getValues(mTmpFloats); + mSurface.setPosition((int)mTmpFloats[Matrix.MTRANS_X], + (int)mTmpFloats[Matrix.MTRANS_Y]); + mSurface.setMatrix( + mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_X], + mTmpFloats[Matrix.MSKEW_Y], mTmpFloats[Matrix.MSCALE_Y]); + + if (false) { + float[] srcPnts = new float[] { 0, 0, mWidth, mHeight }; + float[] dstPnts = new float[8]; + mMatrix.mapPoints(dstPnts, srcPnts); + Slog.i(TAG, "**** ROTATION: " + delta); + Slog.i(TAG, "Original : (" + srcPnts[0] + "," + srcPnts[1] + + ")-(" + srcPnts[2] + "," + srcPnts[3] + ")"); + Slog.i(TAG, "Transformed: (" + dstPnts[0] + "," + dstPnts[1] + + ")-(" + dstPnts[2] + "," + dstPnts[3] + ")"); + } + } + + public void dismiss() { + mSurface.destroy(); + } +} diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index b3ea836..89512ae 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -201,6 +201,12 @@ public class WindowManagerService extends IWindowManager.Stub */ static final int DEFAULT_FADE_IN_OUT_DURATION = 400; + /** + * If true, the window manager will do its own custom freezing and general + * management of the screen during rotation. + */ + static final boolean CUSTOM_SCREEN_ROTATION = true; + // Maximum number of milliseconds to wait for input event injection. // FIXME is this value reasonable? private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; @@ -374,6 +380,7 @@ public class WindowManagerService extends IWindowManager.Stub boolean mBlurShown; Watermark mWatermark; StrictModeFlash mStrictModeFlash; + ScreenRotationAnimation mScreenRotationAnimation; int mTransactionSequence = 0; @@ -4911,6 +4918,10 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void setStrictModeVisualIndicatorPreference(String value) { + SystemProperties.set(StrictMode.VISUAL_PROPERTY, value); + } + public void freezeRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, "setRotation()")) { @@ -4998,7 +5009,18 @@ public class WindowManagerService extends IWindowManager.Stub Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); mInputManager.setDisplayOrientation(0, rotation); if (mDisplayEnabled) { - Surface.setOrientation(0, rotation, animFlags); + if (CUSTOM_SCREEN_ROTATION) { + Surface.freezeDisplay(0); + Surface.openTransaction(); + if (mScreenRotationAnimation != null) { + mScreenRotationAnimation.setRotation(rotation); + } + Surface.closeTransaction(); + Surface.setOrientation(0, rotation, animFlags); + Surface.unfreezeDisplay(0); + } else { + Surface.setOrientation(0, rotation, animFlags); + } } for (int i=mWindows.size()-1; i>=0; i--) { WindowState w = mWindows.get(i); @@ -10817,7 +10839,14 @@ public class WindowManagerService extends IWindowManager.Stub File file = new File("/data/system/frozen"); Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); } - Surface.freezeDisplay(0); + + if (CUSTOM_SCREEN_ROTATION) { + if (mScreenRotationAnimation == null) { + mScreenRotationAnimation = new ScreenRotationAnimation(mDisplay, mFxSession); + } + } else { + Surface.freezeDisplay(0); + } } private void stopFreezingDisplayLocked() { @@ -10834,7 +10863,15 @@ public class WindowManagerService extends IWindowManager.Stub if (PROFILE_ORIENTATION) { Debug.stopMethodTracing(); } - Surface.unfreezeDisplay(0); + + if (CUSTOM_SCREEN_ROTATION) { + if (mScreenRotationAnimation != null) { + mScreenRotationAnimation.dismiss(); + mScreenRotationAnimation = null; + } + } else { + Surface.unfreezeDisplay(0); + } mInputMonitor.thawInputDispatchingLw(); diff --git a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java b/telephony/java/com/android/internal/telephony/ApnSetting.java index 05527af..5af8e35 100644 --- a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java +++ b/telephony/java/com/android/internal/telephony/ApnSetting.java @@ -14,27 +14,26 @@ * limitations under the License. */ -package com.android.internal.telephony.gsm; +package com.android.internal.telephony; -import com.android.internal.telephony.*; /** * This class represents a apn setting for create PDP link */ public class ApnSetting { - String carrier; - String apn; - String proxy; - String port; - String mmsc; - String mmsProxy; - String mmsPort; - String user; - String password; - int authType; + public String carrier; + public String apn; + public String proxy; + public String port; + public String mmsc; + public String mmsProxy; + public String mmsPort; + public String user; + public String password; + public int authType; public String[] types; - int id; - String numeric; + public int id; + public String numeric; public ApnSetting(int id, String numeric, String carrier, String apn, String proxy, String port, diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java index c3ad9e6..2536745 100644 --- a/telephony/java/com/android/internal/telephony/DataConnection.java +++ b/telephony/java/com/android/internal/telephony/DataConnection.java @@ -16,7 +16,6 @@ package com.android.internal.telephony; -import com.android.internal.telephony.gsm.ApnSetting; import com.android.internal.util.HierarchicalState; import com.android.internal.util.HierarchicalStateMachine; diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index 9c738ec..8f3fa1b 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -16,8 +16,6 @@ package com.android.internal.telephony; -import com.android.internal.telephony.cdma.CDMAPhone; - import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; @@ -231,6 +229,9 @@ public abstract class DataConnectionTracker extends Handler { protected HashMap<Integer, DataConnection> mDataConnections = new HashMap<Integer, DataConnection>(); + /* Currently active APN */ + protected ApnSetting mActiveApn; + protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver () { @Override @@ -343,6 +344,40 @@ public abstract class DataConnectionTracker extends Handler { return new ArrayList<DataConnection>(mDataConnections.values()); } + protected boolean isApnTypeActive(String type) { + // TODO: support simultaneous with List instead + return mActiveApn != null && mActiveApn.canHandleType(type); + } + + public String[] getActiveApnTypes() { + String[] result; + if (mActiveApn != null) { + result = mActiveApn.types; + } else { + result = new String[1]; + result[0] = Phone.APN_TYPE_DEFAULT; + } + return result; + } + + public String getActiveApnType() { + String result; + if (mActiveApn != null) { + result = apnIdToType(mActiveApn.id); + } else { + result = null; + } + return result; + } + + protected String getActiveApnString() { + String result = null; + if (mActiveApn != null) { + result = mActiveApn.apn; + } + return result; + } + /** * The data connection is expected to be setup while device * 1. has Icc card @@ -533,14 +568,8 @@ public abstract class DataConnectionTracker extends Handler { } } - protected abstract boolean isApnTypeActive(String type); - protected abstract boolean isApnTypeAvailable(String type); - protected abstract String[] getActiveApnTypes(); - - protected abstract String getActiveApnString(); - protected abstract void setState(State s); protected LinkProperties getLinkProperties(String apnType) { diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java index 8072c44..c645da5 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java @@ -20,7 +20,6 @@ import android.os.Message; import android.util.Log; import com.android.internal.telephony.DataConnection; -import com.android.internal.telephony.gsm.ApnSetting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.RetryManager; diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index d7ff0c5..024ef33 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -32,6 +32,7 @@ import android.text.TextUtils; import android.util.EventLog; import android.util.Log; +import com.android.internal.telephony.ApnSetting; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.DataConnection.FailCause; @@ -39,7 +40,6 @@ import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.RetryManager; -import com.android.internal.telephony.gsm.ApnSetting; import com.android.internal.telephony.Phone; import java.util.ArrayList; @@ -89,9 +89,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { Phone.APN_TYPE_MMS, Phone.APN_TYPE_HIPRI }; - // if we have no active Apn this is null - protected ApnSetting mActiveApn; - /* Constructor */ CdmaDataConnectionTracker(CDMAPhone p) { @@ -158,11 +155,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } @Override - protected boolean isApnTypeActive(String type) { - return mActiveApn != null && mActiveApn.canHandleType(type); - } - - @Override protected boolean isApnTypeAvailable(String type) { for (String s : mSupportedApnTypes) { if (TextUtils.equals(type, s)) { @@ -172,23 +164,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { return false; } - @Override - protected String[] getActiveApnTypes() { - String[] result; - if (mActiveApn != null) { - result = mActiveApn.types; - } else { - result = new String[1]; - result[0] = Phone.APN_TYPE_DEFAULT; - } - return result; - } - - @Override - protected String getActiveApnString() { - return null; - } - /** * The data connection is expected to be setup while device * 1. has ruim card or non-volatile data store diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java index d428099..dfba8d6 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -20,6 +20,7 @@ import android.os.Message; import android.util.Log; import android.util.Patterns; +import com.android.internal.telephony.ApnSetting; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RILConstants; diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index bbfdd31..b41402c 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -40,6 +40,7 @@ import android.util.EventLog; import android.util.Log; import com.android.internal.R; +import com.android.internal.telephony.ApnSetting; import com.android.internal.telephony.DataCallState; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataConnectionTracker; @@ -108,9 +109,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private int mWaitingApnsPermanentFailureCountDown = 0; private ApnSetting mPreferredApn = null; - /* Currently active APN */ - protected ApnSetting mActiveApn; - /** The DataConnection being setup */ private GsmDataConnection mPendingDataConnection; @@ -211,27 +209,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } - @Override - public String[] getActiveApnTypes() { - String[] result; - if (mActiveApn != null) { - result = mActiveApn.types; - } else { - result = new String[1]; - result[0] = Phone.APN_TYPE_DEFAULT; - } - return result; - } - - @Override - protected String getActiveApnString() { - String result = null; - if (mActiveApn != null) { - result = mActiveApn.apn; - } - return result; - } - /** * The data connection is expected to be setup while device * 1. has sim card @@ -256,12 +233,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } @Override - protected boolean isApnTypeActive(String type) { - // TODO: support simultaneous with List instead - return mActiveApn != null && mActiveApn.canHandleType(type); - } - - @Override protected boolean isApnTypeAvailable(String type) { if (type.equals(Phone.APN_TYPE_DUN)) { return (fetchDunApn() != null); diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java index d545018..56beada 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java @@ -112,6 +112,7 @@ public class FileFilter { ignoreResultList.add("fast/events/touch/touch-coords-in-zoom-and-scroll.html"); // Requires eventSender.zoomPageIn(),zoomPageOut() ignoreResultList.add("fast/events/touch/touch-target.html"); // Requires multi-touch gestures not supported by Android system ignoreResultList.add("fast/workers"); // workers not supported + ignoreResultList.add("http/tests/cookies/third-party-cookie-relaxing.html"); // We don't support conditional acceptance of third-party cookies ignoreResultList.add("http/tests/eventsource/workers"); // workers not supported ignoreResultList.add("http/tests/workers"); // workers not supported ignoreResultList.add("http/tests/xmlhttprequest/workers"); // workers not supported diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp index f0d2fee..6ec223b 100644 --- a/tools/validatekeymaps/Main.cpp +++ b/tools/validatekeymaps/Main.cpp @@ -42,7 +42,7 @@ static void usage() { } static FileType getFileType(const char* filename) { - char *extension = strrchr(filename, '.'); + const char *extension = strrchr(filename, '.'); if (extension) { if (strcmp(extension, ".kl") == 0) { return FILETYPE_KEYLAYOUT; |