diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 324 | ||||
| -rw-r--r-- | core/java/android/hardware/Camera.java | 43 | ||||
| -rw-r--r-- | core/java/android/provider/ContactsContract.java | 10 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 90 | ||||
| -rwxr-xr-x | core/java/android/view/InputDevice.java | 10 | ||||
| -rw-r--r-- | core/java/android/view/KeyCharacterMap.java | 15 | ||||
| -rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 3 | ||||
| -rw-r--r-- | core/java/android/view/textservice/SpellCheckerSession.java | 3 | ||||
| -rw-r--r-- | core/java/android/webkit/WebView.java | 28 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 35 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/DigitalClock.java | 3 |
11 files changed, 340 insertions, 224 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f9896f7..303f81b 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2734,8 +2734,9 @@ public final class ActivityThread { CharSequence description; } - private class ProviderRefCount { + private static final class ProviderRefCount { public int count; + ProviderRefCount(int pCount) { count = pCount; } @@ -3988,16 +3989,14 @@ public final class ActivityThread { buf.append(": "); buf.append(cpi.name); Log.i(TAG, buf.toString()); - IContentProvider cp = installProvider(context, null, cpi, false); + IContentProvider cp = installProvider(context, null, cpi, + false /*noisy*/, true /*noReleaseNeeded*/); if (cp != null) { IActivityManager.ContentProviderHolder cph = - new IActivityManager.ContentProviderHolder(cpi); + new IActivityManager.ContentProviderHolder(cpi); cph.provider = cp; + cph.noReleaseNeeded = true; results.add(cph); - // Don't ever unload this provider from the process. - synchronized(mProviderMap) { - mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000)); - } } } @@ -4008,26 +4007,22 @@ public final class ActivityThread { } } - private IContentProvider getExistingProvider(Context context, String name) { - synchronized(mProviderMap) { - final ProviderClientRecord pr = mProviderMap.get(name); - if (pr != null) { - return pr.mProvider; - } - return null; - } - } - - private IContentProvider getProvider(Context context, String name) { - IContentProvider existing = getExistingProvider(context, name); - if (existing != null) { - return existing; + public final IContentProvider acquireProvider(Context c, String name) { + IContentProvider provider = acquireExistingProvider(c, name); + if (provider != null) { + return provider; } + // There is a possible race here. Another thread may try to acquire + // the same provider at the same time. When this happens, we want to ensure + // that the first one wins. + // Note that we cannot hold the lock while acquiring and installing the + // provider since it might take a long time to run and it could also potentially + // be re-entrant in the case where the provider is in the same process. IActivityManager.ContentProviderHolder holder = null; try { holder = ActivityManagerNative.getDefault().getContentProvider( - getApplicationThread(), name); + getApplicationThread(), name); } catch (RemoteException ex) { } if (holder == null) { @@ -4035,135 +4030,136 @@ public final class ActivityThread { return null; } - IContentProvider prov = installProvider(context, holder.provider, - holder.info, true); - //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded); - if (holder.noReleaseNeeded || holder.provider == null) { - // We are not going to release the provider if it is an external - // provider that doesn't care about being released, or if it is - // a local provider running in this process. - //Slog.i(TAG, "*** NO RELEASE NEEDED"); - synchronized(mProviderMap) { - mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000)); + // Install provider will increment the reference count for us, and break + // any ties in the race. + provider = installProvider(c, holder.provider, holder.info, + true /*noisy*/, holder.noReleaseNeeded); + if (holder.provider != null && provider != holder.provider) { + if (localLOGV) { + Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous " + + "reference to the content provider"); + } + try { + ActivityManagerNative.getDefault().removeContentProvider( + getApplicationThread(), name); + } catch (RemoteException ex) { } } - return prov; - } - - public final IContentProvider acquireProvider(Context c, String name) { - IContentProvider provider = getProvider(c, name); - if(provider == null) - return null; - IBinder jBinder = provider.asBinder(); - synchronized(mProviderMap) { - ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc == null) { - mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); - } else { - prc.count++; - } //end else - } //end synchronized return provider; } public final IContentProvider acquireExistingProvider(Context c, String name) { - IContentProvider provider = getExistingProvider(c, name); - if(provider == null) - return null; - IBinder jBinder = provider.asBinder(); - synchronized(mProviderMap) { + synchronized (mProviderMap) { + ProviderClientRecord pr = mProviderMap.get(name); + if (pr == null) { + return null; + } + + IContentProvider provider = pr.mProvider; + IBinder jBinder = provider.asBinder(); + + // Only increment the ref count if we have one. If we don't then the + // provider is not reference counted and never needs to be released. ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc == null) { - mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); - } else { - prc.count++; - } //end else - } //end synchronized - return provider; + if (prc != null) { + prc.count += 1; + if (prc.count == 1) { + if (localLOGV) { + Slog.v(TAG, "acquireExistingProvider: " + + "snatched provider from the jaws of death"); + } + // Because the provider previously had a reference count of zero, + // it was scheduled to be removed. Cancel that. + mH.removeMessages(H.REMOVE_PROVIDER, provider); + } + } + return provider; + } } public final boolean releaseProvider(IContentProvider provider) { if(provider == null) { return false; } + IBinder jBinder = provider.asBinder(); - synchronized(mProviderMap) { + synchronized (mProviderMap) { ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc == null) { - if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here"); + if (prc == null) { + // The provider has no ref count, no release is needed. return false; - } else { - prc.count--; - if(prc.count == 0) { - // Schedule the actual remove asynchronously, since we - // don't know the context this will be called in. - // TODO: it would be nice to post a delayed message, so - // if we come back and need the same provider quickly - // we will still have it available. - Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider); - mH.sendMessage(msg); - } //end if - } //end else - } //end synchronized - return true; + } + + if (prc.count == 0) { + if (localLOGV) Slog.v(TAG, "releaseProvider: ref count already 0, how?"); + return false; + } + + prc.count -= 1; + if (prc.count == 0) { + // Schedule the actual remove asynchronously, since we don't know the context + // this will be called in. + // TODO: it would be nice to post a delayed message, so + // if we come back and need the same provider quickly + // we will still have it available. + Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider); + mH.sendMessage(msg); + } + return true; + } } final void completeRemoveProvider(IContentProvider provider) { IBinder jBinder = provider.asBinder(); - String name = null; + String remoteProviderName = null; synchronized(mProviderMap) { ProviderRefCount prc = mProviderRefCountMap.get(jBinder); - if(prc != null && prc.count == 0) { - mProviderRefCountMap.remove(jBinder); - //invoke removeProvider to dereference provider - name = removeProviderLocked(provider); + if (prc == null) { + // Either no release is needed (so we shouldn't be here) or the + // provider was already released. + if (localLOGV) Slog.v(TAG, "completeRemoveProvider: release not needed"); + return; + } + + if (prc.count != 0) { + // There was a race! Some other client managed to acquire + // the provider before the removal was completed. + // Abort the removal. We will do it later. + if (localLOGV) Slog.v(TAG, "completeRemoveProvider: lost the race, " + + "provider still in use"); + return; + } + + mProviderRefCountMap.remove(jBinder); + + Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator(); + while (iter.hasNext()) { + ProviderClientRecord pr = iter.next(); + IBinder myBinder = pr.mProvider.asBinder(); + if (myBinder == jBinder) { + iter.remove(); + if (pr.mLocalProvider == null) { + myBinder.unlinkToDeath(pr, 0); + if (remoteProviderName == null) { + remoteProviderName = pr.mName; + } + } + } } } - - if (name != null) { + + if (remoteProviderName != null) { try { - if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " + - "ActivityManagerNative.removeContentProvider(" + name); + if (localLOGV) { + Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative." + + "removeContentProvider(" + remoteProviderName + ")"); + } ActivityManagerNative.getDefault().removeContentProvider( - getApplicationThread(), name); + getApplicationThread(), remoteProviderName); } catch (RemoteException e) { //do nothing content provider object is dead any way - } //end catch - } - } - - public final String removeProviderLocked(IContentProvider provider) { - if (provider == null) { - return null; + } } - IBinder providerBinder = provider.asBinder(); - - String name = null; - - // remove the provider from mProviderMap - Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator(); - while (iter.hasNext()) { - ProviderClientRecord pr = iter.next(); - IBinder myBinder = pr.mProvider.asBinder(); - if (myBinder == providerBinder) { - //find if its published by this process itself - if(pr.mLocalProvider != null) { - if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning"); - return name; - } - if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " + - "death recipient"); - //content provider is in another process - myBinder.unlinkToDeath(pr, 0); - iter.remove(); - //invoke remove only once for the very first name seen - if(name == null) { - name = pr.mName; - } - } //end if myBinder - } //end while iter - - return name; } final void removeDeadProvider(String name, IContentProvider provider) { @@ -4179,8 +4175,23 @@ public final class ActivityThread { } } + /** + * Installs the provider. + * + * Providers that are local to the process or that come from the system server + * may be installed permanently which is indicated by setting noReleaseNeeded to true. + * Other remote providers are reference counted. The initial reference count + * for all reference counted providers is one. Providers that are not reference + * counted do not have a reference count (at all). + * + * This method detects when a provider has already been installed. When this happens, + * it increments the reference count of the existing provider (if appropriate) + * and returns the existing provider. This can happen due to concurrent + * attempts to acquire the same provider. + */ private IContentProvider installProvider(Context context, - IContentProvider provider, ProviderInfo info, boolean noisy) { + IContentProvider provider, ProviderInfo info, + boolean noisy, boolean noReleaseNeeded) { ContentProvider localProvider = null; if (provider == null) { if (noisy) { @@ -4238,24 +4249,69 @@ public final class ActivityThread { } synchronized (mProviderMap) { - // Cache the pointer for the remote provider. + // There is a possibility that this thread raced with another thread to + // add the provider. If we find another thread got there first then we + // just get out of the way and return the original provider. + IBinder jBinder = provider.asBinder(); String names[] = PATTERN_SEMICOLON.split(info.authority); - for (int i=0; i<names.length; i++) { - ProviderClientRecord pr = new ProviderClientRecord(names[i], provider, - localProvider); - try { - provider.asBinder().linkToDeath(pr, 0); + for (int i = 0; i < names.length; i++) { + ProviderClientRecord pr = mProviderMap.get(names[i]); + if (pr != null) { + if (localLOGV) { + Slog.v(TAG, "installProvider: lost the race, " + + "using existing named provider"); + } + provider = pr.mProvider; + } else { + pr = new ProviderClientRecord(names[i], provider, localProvider); + if (localProvider == null) { + try { + jBinder.linkToDeath(pr, 0); + } catch (RemoteException e) { + // Provider already dead. Bail out of here without making + // any changes to the provider map or other data structures. + return null; + } + } mProviderMap.put(names[i], pr); - } catch (RemoteException e) { - return null; } } + if (localProvider != null) { - mLocalProviders.put(provider.asBinder(), - new ProviderClientRecord(null, provider, localProvider)); + ProviderClientRecord pr = mLocalProviders.get(jBinder); + if (pr != null) { + if (localLOGV) { + Slog.v(TAG, "installProvider: lost the race, " + + "using existing local provider"); + } + provider = pr.mProvider; + } else { + pr = new ProviderClientRecord(null, provider, localProvider); + mLocalProviders.put(jBinder, pr); + } } - } + if (!noReleaseNeeded) { + ProviderRefCount prc = mProviderRefCountMap.get(jBinder); + if (prc != null) { + if (localLOGV) { + Slog.v(TAG, "installProvider: lost the race, incrementing ref count"); + } + prc.count += 1; + if (prc.count == 1) { + if (localLOGV) { + Slog.v(TAG, "installProvider: " + + "snatched provider from the jaws of death"); + } + // Because the provider previously had a reference count of zero, + // it was scheduled to be removed. Cancel that. + mH.removeMessages(H.REMOVE_PROVIDER, provider); + } + } else { + mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); + } + } + } return provider; } diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 3becec0..c2a757f 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -1111,9 +1111,21 @@ public class Camera { * Parameters#getMaxNumDetectedFaces()} returns a number larger than 0. * If the face detection has started, apps should not call this again. * - * When the face detection is running, {@link Parameters#setWhiteBalance(String)}, + * <p>When the face detection is running, {@link Parameters#setWhiteBalance(String)}, * {@link Parameters#setFocusAreas(List)}, and {@link Parameters#setMeteringAreas(List)} - * have no effect. + * have no effect. The camera uses the detected faces to do auto-white balance, + * auto exposure, and autofocus. + * + * <p>If the apps call {@link #autoFocus(AutoFocusCallback)}, the camera + * will stop sending face callbacks. The last face callback indicates the + * areas used to do autofocus. After focus completes, face detection will + * resume sending face callbacks. If the apps call {@link + * #cancelAutoFocus()}, the face callbacks will also resume.</p> + * + * <p>After calling {@link #takePicture(Camera.ShutterCallback, Camera.PictureCallback, + * Camera.PictureCallback)} or {@link #stopPreview()}, and then resuming + * preview with {@link #startPreview()}, the apps should call this method + * again to resume face detection.</p> * * @throws IllegalArgumentException if the face detection is unsupported. * @throws RuntimeException if the method fails or the face detection is @@ -1163,14 +1175,31 @@ public class Camera { * camera field of view, and (1000, 1000) represents the bottom-right of * the field of view. For example, suppose the size of the viewfinder UI * is 800x480. The rect passed from the driver is (-1000, -1000, 0, 0). - * The corresponding viewfinder rect should be (0, 0, 400, 240). The - * width and height of the rect will not be 0 or negative. The - * coordinates can be smaller than -1000 or bigger than 1000. But at - * least one vertex will be within (-1000, -1000) and (1000, 1000). + * The corresponding viewfinder rect should be (0, 0, 400, 240). It is + * guaranteed left < right and top < bottom. The coordinates can be + * smaller than -1000 or bigger than 1000. But at least one vertex will + * be within (-1000, -1000) and (1000, 1000). * * <p>The direction is relative to the sensor orientation, that is, what * the sensor sees. The direction is not affected by the rotation or - * mirroring of {@link #setDisplayOrientation(int)}.</p> + * mirroring of {@link #setDisplayOrientation(int)}. The face bounding + * rectangle does not provide any information about face orientation.</p> + * + * <p>Here is the matrix to convert driver coordinates to View coordinates + * in pixels.</p> + * <pre> + * Matrix matrix = new Matrix(); + * CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId]; + * // Need mirror for front camera. + * boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); + * matrix.setScale(mirror ? -1 : 1, 1); + * // This is the value for android.hardware.Camera.setDisplayOrientation. + * matrix.postRotate(displayOrientation); + * // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). + * // UI coordinates range from (0, 0) to (width, height). + * matrix.postScale(view.getWidth() / 2000f, view.getHeight() / 2000f); + * matrix.postTranslate(view.getWidth() / 2f, view.getHeight() / 2f); + * </pre> * * @see #startFaceDetection() */ diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 821b6df..83acef8 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -187,6 +187,16 @@ public final class ContactsContract { public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query"; /** + * A boolean parameter for {@link CommonDataKinds.Phone#CONTENT_URI}, + * {@link CommonDataKinds.Email#CONTENT_URI}, and + * {@link CommonDataKinds.StructuredPostal#CONTENT_URI}. + * This enables a content provider to remove duplicate entries in results. + * + * @hide + */ + public static final String REMOVE_DUPLICATE_ENTRIES = "remove_duplicate_entries"; + + /** * <p> * API for obtaining a pre-authorized version of a URI that normally requires special * permission (beyond READ_CONTACTS) to read. The caller obtaining the pre-authorized URI diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index e0167d8..8e39d6e 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -22,6 +22,9 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.opengl.GLUtils; +import android.opengl.ManagedEGLContext; +import android.os.Handler; +import android.os.Looper; import android.os.SystemClock; import android.os.SystemProperties; import android.util.Log; @@ -409,7 +412,8 @@ public abstract class HardwareRenderer { static final Object[] sEglLock = new Object[0]; int mWidth = -1, mHeight = -1; - static final ThreadLocal<EGLContext> sEglContextStorage = new ThreadLocal<EGLContext>(); + static final ThreadLocal<Gl20Renderer.MyEGLContext> sEglContextStorage + = new ThreadLocal<Gl20Renderer.MyEGLContext>(); EGLContext mEglContext; Thread mEglThread; @@ -561,12 +565,13 @@ public abstract class HardwareRenderer { } } - mEglContext = sEglContextStorage.get(); + Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get(); + mEglContext = managedContext != null ? managedContext.getContext() : null; mEglThread = Thread.currentThread(); if (mEglContext == null) { mEglContext = createContext(sEgl, sEglDisplay, sEglConfig); - sEglContextStorage.set(mEglContext); + sEglContextStorage.set(new Gl20Renderer.MyEGLContext(mEglContext)); } } @@ -904,6 +909,51 @@ public abstract class HardwareRenderer { private static EGLSurface sPbuffer; private static final Object[] sPbufferLock = new Object[0]; + static class MyEGLContext extends ManagedEGLContext { + final Handler mHandler = new Handler(); + + public MyEGLContext(EGLContext context) { + super(context); + } + + @Override + public void onTerminate(final EGLContext eglContext) { + // Make sure we do this on the correct thread. + if (mHandler.getLooper() != Looper.myLooper()) { + mHandler.post(new Runnable() { + @Override public void run() { + onTerminate(eglContext); + } + }); + return; + } + + synchronized (sEglLock) { + if (sEgl == null) return; + + if (EGLImpl.getInitCount(sEglDisplay) == 1) { + usePbufferSurface(eglContext); + GLES20Canvas.terminateCaches(); + + sEgl.eglDestroyContext(sEglDisplay, eglContext); + sEglContextStorage.remove(); + + sEgl.eglDestroySurface(sEglDisplay, sPbuffer); + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + sEgl.eglReleaseThread(); + sEgl.eglTerminate(sEglDisplay); + + sEgl = null; + sEglDisplay = null; + sEglConfig = null; + sPbuffer = null; + sEglContextStorage.set(null); + } + } + } + } + Gl20Renderer(boolean translucent) { super(2, translucent); } @@ -1020,12 +1070,12 @@ public abstract class HardwareRenderer { static void trimMemory(int level) { if (sEgl == null || sEglConfig == null) return; - EGLContext eglContext = sEglContextStorage.get(); + Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get(); // We do not have OpenGL objects - if (eglContext == null) { + if (managedContext == null) { return; } else { - usePbufferSurface(eglContext); + usePbufferSurface(managedContext.getContext()); } switch (level) { @@ -1052,33 +1102,5 @@ public abstract class HardwareRenderer { } sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext); } - - static void terminate() { - synchronized (sEglLock) { - if (sEgl == null) return; - - if (EGLImpl.getInitCount(sEglDisplay) == 1) { - EGLContext eglContext = sEglContextStorage.get(); - if (eglContext == null) return; - - usePbufferSurface(eglContext); - GLES20Canvas.terminateCaches(); - - sEgl.eglDestroyContext(sEglDisplay, eglContext); - sEglContextStorage.remove(); - - sEgl.eglDestroySurface(sEglDisplay, sPbuffer); - sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - sEgl.eglReleaseThread(); - sEgl.eglTerminate(sEglDisplay); - - sEgl = null; - sEglDisplay = null; - sEglConfig = null; - sPbuffer = null; - } - } - } } } diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index bfc7c31..8115b36 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -19,7 +19,6 @@ package android.view; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; -import android.os.ServiceManager; import java.util.ArrayList; import java.util.List; @@ -44,6 +43,7 @@ public final class InputDevice implements Parcelable { private String mName; private int mSources; private int mKeyboardType; + private String mKeyCharacterMapFile; private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>(); @@ -360,6 +360,10 @@ public final class InputDevice implements Parcelable { return KeyCharacterMap.load(mId); } + String getKeyCharacterMapFile() { + return mKeyCharacterMapFile; + } + /** * Gets information about the range of values for a particular {@link MotionEvent} axis. * If the device supports multiple sources, the same axis may have different meanings @@ -532,6 +536,7 @@ public final class InputDevice implements Parcelable { mName = in.readString(); mSources = in.readInt(); mKeyboardType = in.readInt(); + mKeyCharacterMapFile = in.readString(); for (;;) { int axis = in.readInt(); @@ -549,6 +554,7 @@ public final class InputDevice implements Parcelable { out.writeString(mName); out.writeInt(mSources); out.writeInt(mKeyboardType); + out.writeString(mKeyCharacterMapFile); final int numRanges = mMotionRanges.size(); for (int i = 0; i < numRanges; i++) { @@ -587,6 +593,8 @@ public final class InputDevice implements Parcelable { } description.append("\n"); + description.append(" Key Character Map: ").append(mKeyCharacterMapFile).append("\n"); + description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index 885a75f..575af3b 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -20,7 +20,6 @@ import android.text.method.MetaKeyKeyListener; import android.util.AndroidRuntimeException; import android.util.SparseIntArray; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.SparseArray; import java.lang.Character; @@ -140,7 +139,7 @@ public class KeyCharacterMap { private final int mDeviceId; private int mPtr; - private static native int nativeLoad(int id); + private static native int nativeLoad(String file); private static native void nativeDispose(int ptr); private static native char nativeGetCharacter(int ptr, int keyCode, int metaState); @@ -178,7 +177,17 @@ public class KeyCharacterMap { synchronized (sInstances) { KeyCharacterMap map = sInstances.get(deviceId); if (map == null) { - int ptr = nativeLoad(deviceId); // might throw + String kcm = null; + if (deviceId != VIRTUAL_KEYBOARD) { + InputDevice device = InputDevice.getDevice(deviceId); + if (device != null) { + kcm = device.getKeyCharacterMapFile(); + } + } + if (kcm == null || kcm.length() == 0) { + kcm = "/system/usr/keychars/Virtual.kcm"; + } + int ptr = nativeLoad(kcm); // might throw map = new KeyCharacterMap(deviceId, ptr); sInstances.put(deviceId, map); } diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index d89bc36..660e3f4 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -21,6 +21,7 @@ import android.content.ComponentCallbacks2; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.PixelFormat; +import android.opengl.ManagedEGLContext; import android.os.IBinder; import android.util.AndroidRuntimeException; import android.util.Log; @@ -428,7 +429,7 @@ public class WindowManagerImpl implements WindowManager { } } // Terminate the hardware renderer to free all resources - HardwareRenderer.terminate(); + ManagedEGLContext.doTerminate(); break; } // high end gfx devices fall through to next case diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java index 0eb6e27..489587e 100644 --- a/core/java/android/view/textservice/SpellCheckerSession.java +++ b/core/java/android/view/textservice/SpellCheckerSession.java @@ -201,7 +201,7 @@ public class SpellCheckerSession { private static final int TASK_CLOSE = 3; private final Queue<SpellCheckerParams> mPendingTasks = new LinkedList<SpellCheckerParams>(); - private final Handler mHandler; + private Handler mHandler; private boolean mOpened; private ISpellCheckerSession mISpellCheckerSession; @@ -334,6 +334,7 @@ public class SpellCheckerSession { try { mISpellCheckerSession.onClose(); mISpellCheckerSession = null; + mHandler = null; } catch (RemoteException e) { Log.e(TAG, "Failed to close " + e); } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 342c6c5..907e8db 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -3103,10 +3103,7 @@ public class WebView extends AbsoluteLayout // Special-case layer scrolling so that we do not trigger normal scroll // updating. if (mTouchMode == TOUCH_DRAG_LAYER_MODE) { - nativeScrollLayer(mScrollingLayer, scrollX, scrollY); - mScrollingLayerRect.left = scrollX; - mScrollingLayerRect.top = scrollY; - invalidate(); + scrollLayerTo(scrollX, scrollY); return; } mInOverScrollMode = false; @@ -3609,9 +3606,7 @@ public class WebView extends AbsoluteLayout mScrollY = y; } else { // Update the layer position instead of WebView. - nativeScrollLayer(mScrollingLayer, x, y); - mScrollingLayerRect.left = x; - mScrollingLayerRect.top = y; + scrollLayerTo(x, y); } abortAnimation(); nativeSetIsScrolling(false); @@ -3630,6 +3625,17 @@ public class WebView extends AbsoluteLayout } } + private void scrollLayerTo(int x, int y) { + if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) { + return; + } + nativeScrollLayer(mScrollingLayer, x, y); + mScrollingLayerRect.left = x; + mScrollingLayerRect.top = y; + onScrollChanged(mScrollX, mScrollY, mScrollX, mScrollY); + invalidate(); + } + private static int computeDuration(int dx, int dy) { int distance = Math.max(Math.abs(dx), Math.abs(dy)); int duration = distance * 1000 / STD_SPEED; @@ -8315,12 +8321,8 @@ public class WebView extends AbsoluteLayout if (mScrollingLayer == 0) { pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0); } else { - mScrollingLayerRect.left += mAutoScrollX; - mScrollingLayerRect.top += mAutoScrollY; - nativeScrollLayer(mScrollingLayer, - mScrollingLayerRect.left, - mScrollingLayerRect.top); - invalidate(); + scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX, + mScrollingLayerRect.top + mAutoScrollY); } sendEmptyMessageDelayed( SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index b106cc5..185cfa9 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -131,7 +131,6 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.InputMethodSubtype; import android.view.textservice.SpellCheckerSubtype; import android.view.textservice.TextServicesManager; import android.widget.AdapterView.OnItemClickListener; @@ -3786,7 +3785,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return; } } - + // This is the handling for some default action. // Note that for backwards compatibility we don't do this // default handling if explicit ime options have not been given, @@ -5342,7 +5341,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (keyCode) { case KeyEvent.KEYCODE_ENTER: - mEnterKeyIsDown = true; if (event.hasNoModifiers()) { // When mInputContentType is set, we know that we are // running in a "modern" cupcake environment, so don't need @@ -5374,7 +5372,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; case KeyEvent.KEYCODE_DPAD_CENTER: - mDPadCenterIsDown = true; if (event.hasNoModifiers()) { if (shouldAdvanceFocusOnEnter()) { return 0; @@ -5488,7 +5485,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: - mDPadCenterIsDown = false; if (event.hasNoModifiers()) { /* * If there is a click listener, just call through to @@ -5513,7 +5509,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return super.onKeyUp(keyCode, event); case KeyEvent.KEYCODE_ENTER: - mEnterKeyIsDown = false; if (event.hasNoModifiers()) { if (mInputContentType != null && mInputContentType.onEditorActionListener != null @@ -5599,6 +5594,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener outAttrs.extras = mInputContentType.extras; } else { outAttrs.imeOptions = EditorInfo.IME_NULL; + // May not be defined otherwise and needed by onEditorAction + mInputContentType = new InputContentType(); } if (focusSearch(FOCUS_DOWN) != null) { outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT; @@ -8972,17 +8969,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private long getLastTouchOffsets() { - int minOffset, maxOffset; - - if (mContextMenuTriggeredByKey) { - minOffset = getSelectionStart(); - maxOffset = getSelectionEnd(); - } else { - SelectionModifierCursorController selectionController = getSelectionController(); - minOffset = selectionController.getMinTouchOffset(); - maxOffset = selectionController.getMaxTouchOffset(); - } - + SelectionModifierCursorController selectionController = getSelectionController(); + final int minOffset = selectionController.getMinTouchOffset(); + final int maxOffset = selectionController.getMaxTouchOffset(); return packRangeInLong(minOffset, maxOffset); } @@ -9075,12 +9064,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private static final int ID_COPY = android.R.id.copy; private static final int ID_PASTE = android.R.id.paste; - private class MenuHandler implements MenuItem.OnMenuItemClickListener { - public boolean onMenuItemClick(MenuItem item) { - return onTextContextMenuItem(item.getItemId()); - } - } - /** * Called when a context menu option for the text view is selected. Currently * this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut}, @@ -11480,12 +11463,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mSelectionControllerEnabled; private boolean mInBatchEditControllers; - // These are needed to desambiguate a long click. If the long click comes from ones of these, we - // select from the current cursor position. Otherwise, select from long pressed position. - private boolean mDPadCenterIsDown = false; - private boolean mEnterKeyIsDown = false; - private boolean mContextMenuTriggeredByKey = false; - private boolean mSelectAllOnFocus = false; private int mGravity = Gravity.TOP | Gravity.START; diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java index 6f24eba..daefc9a 100644 --- a/core/java/com/android/internal/widget/DigitalClock.java +++ b/core/java/com/android/internal/widget/DigitalClock.java @@ -106,7 +106,8 @@ public class DigitalClock extends RelativeLayout { private String mAmString, mPmString; AmPm(View parent, Typeface tf) { - mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm); + // No longer used, uncomment if we decide to use AM/PM indicator again + // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm); if (mAmPmTextView != null && tf != null) { mAmPmTextView.setTypeface(tf); } |
