Merge "Fix bug 4064086 Use a death handler on audio focus changes from mode" into honeycomb-mr1
diff --git a/api/current.xml b/api/current.xml
index 557590a..cbccf93 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -95457,6 +95457,32 @@
visibility="public"
>
</method>
+<method name="hasPermission"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.hardware.usb.UsbDevice">
+</parameter>
+</method>
+<method name="hasPermission"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="accessory" type="android.hardware.usb.UsbAccessory">
+</parameter>
+</method>
<method name="isFunctionEnabled"
return="boolean"
abstract="false"
@@ -95509,6 +95535,36 @@
<parameter name="device" type="android.hardware.usb.UsbDevice">
</parameter>
</method>
+<method name="requestPermission"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.hardware.usb.UsbDevice">
+</parameter>
+<parameter name="pi" type="android.app.PendingIntent">
+</parameter>
+</method>
+<method name="requestPermission"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="accessory" type="android.hardware.usb.UsbAccessory">
+</parameter>
+<parameter name="pi" type="android.app.PendingIntent">
+</parameter>
+</method>
<field name="ACTION_USB_ACCESSORY_ATTACHED"
type="java.lang.String"
transient="false"
@@ -95586,6 +95642,17 @@
visibility="public"
>
</field>
+<field name="EXTRA_PERMISSION_GRANTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""permission""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="USB_CONFIGURATION"
type="java.lang.String"
transient="false"
@@ -207176,21 +207243,6 @@
visibility="public"
>
</method>
-<method name="entryEvicted"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="protected"
->
-<parameter name="key" type="K">
-</parameter>
-<parameter name="value" type="V">
-</parameter>
-</method>
<method name="entryRemoved"
return="void"
abstract="false"
@@ -244871,6 +244923,25 @@
<parameter name="realm" type="java.lang.String">
</parameter>
</method>
+<method name="onReceivedLoginRequest"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.webkit.WebView">
+</parameter>
+<parameter name="realm" type="java.lang.String">
+</parameter>
+<parameter name="account" type="java.lang.String">
+</parameter>
+<parameter name="args" type="java.lang.String">
+</parameter>
+</method>
<method name="onReceivedSslError"
return="void"
abstract="false"
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 539e946..cc1f81c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -401,10 +401,10 @@
return new UiModeManager();
}});
- registerService(USB_SERVICE, new StaticServiceFetcher() {
- public Object createStaticService() {
+ registerService(USB_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(USB_SERVICE);
- return new UsbManager(IUsbManager.Stub.asInterface(b));
+ return new UsbManager(ctx, IUsbManager.Stub.asInterface(b));
}});
registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 440cb54..efe2633 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1150,8 +1150,12 @@
* fail (most commonly returning {@link #ENCRYPTION_STATUS_ACTIVE}).
*
* <p>This policy controls encryption of the secure (application data) storage area. Data
- * written to other areas (e.g. the directory returned by
- * {@link android.os.Environment#getExternalStorageDirectory()} may or may not be encrypted.
+ * written to other storage areas may or may not be encrypted, and this policy does not require
+ * or control the encryption of any other storage areas.
+ * There is one exception: If {@link android.os.Environment#isExternalStorageEmulated()} is
+ * {@code true}, then the directory returned by
+ * {@link android.os.Environment#getExternalStorageDirectory()} must be written to disk
+ * within the encrypted storage area.
*
* <p>Important Note: On some devices, it is possible to encrypt storage without requiring
* the user to create a device PIN or Password. In this case, the storage is encrypted, but
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index be65bdb..c79a458 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -16,6 +16,7 @@
package android.hardware.usb;
+import android.app.PendingIntent;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.os.Bundle;
@@ -50,6 +51,25 @@
*/
void setAccessoryPackage(in UsbAccessory accessory, String packageName);
+ /* Returns true if the caller has permission to access the device. */
+ boolean hasDevicePermission(in UsbDevice device);
+
+ /* Returns true if the caller has permission to access the accessory. */
+ boolean hasAccessoryPermission(in UsbAccessory accessory);
+
+ /* Requests permission for the given package to access the device.
+ * Will display a system dialog to query the user if permission
+ * had not already been given.
+ */
+ void requestDevicePermission(in UsbDevice device, String packageName, in PendingIntent pi);
+
+ /* Requests permission for the given package to access the accessory.
+ * Will display a system dialog to query the user if permission
+ * had not already been given. Result is returned via pi.
+ */
+ void requestAccessoryPermission(in UsbAccessory accessory, String packageName,
+ in PendingIntent pi);
+
/* Grants permission for the given UID to access the device */
void grantDevicePermission(in UsbDevice device, int uid);
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 6683179..9f1b8ea 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -17,6 +17,8 @@
package android.hardware.usb;
+import android.app.PendingIntent;
+import android.content.Context;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -176,12 +178,24 @@
*/
public static final String EXTRA_ACCESSORY = "accessory";
- private IUsbManager mService;
+ /**
+ * Name of extra added to the {@link android.app.PendingIntent}
+ * passed into
+ * {#requestPermission(android.content.Context, android.hardware.usb.UsbDevice, android.app.PendingIntent)}
+ * or
+ * {#requestPermission(android.content.Context, android.hardware.usb.UsbAccessory, android.app.PendingIntent)}
+ * containing a boolean value indicating whether the user granted permission or not.
+ */
+ public static final String EXTRA_PERMISSION_GRANTED = "permission";
+
+ private final Context mContext;
+ private final IUsbManager mService;
/**
* {@hide}
*/
- public UsbManager(IUsbManager service) {
+ public UsbManager(Context context, IUsbManager service) {
+ mContext = context;
mService = service;
}
@@ -245,7 +259,7 @@
return new UsbAccessory[] { accessory };
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getAccessoryList" , e);
+ Log.e(TAG, "RemoteException in getAccessoryList", e);
return null;
}
}
@@ -260,11 +274,87 @@
try {
return mService.openAccessory(accessory);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openAccessory" , e);
+ Log.e(TAG, "RemoteException in openAccessory", e);
return null;
}
}
+ /**
+ * Returns true if the caller has permission to access the device.
+ *
+ * @param device to check permissions for
+ * @return true if caller has permission
+ */
+ public boolean hasPermission(UsbDevice device) {
+ try {
+ return mService.hasDevicePermission(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in hasPermission", e);
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the caller has permission to access the accessory.
+ *
+ * @param accessory to check permissions for
+ * @return true if caller has permission
+ */
+ public boolean hasPermission(UsbAccessory accessory) {
+ try {
+ return mService.hasAccessoryPermission(accessory);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in hasPermission", e);
+ return false;
+ }
+ }
+
+ /**
+ * Requests permission for the given package to access the device.
+ * This may result in a system dialog being displayed to the user
+ * if permission had not already been granted.
+ * Success or failure is returned via the {@link android.app.PendingIntent} pi.
+ * The following extras will be added to pi:
+ * <ul>
+ * <li> {@link #EXTRA_DEVICE} containing the device passed into this call
+ * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether
+ * permission was granted by the user
+ * </ul>
+ *
+ * @param device to request permissions for
+ * @param pi PendingIntent for returning result
+ */
+ public void requestPermission(UsbDevice device, PendingIntent pi) {
+ try {
+ mService.requestDevicePermission(device, mContext.getPackageName(), pi);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in requestPermission", e);
+ }
+ }
+
+ /**
+ * Requests permission for the given package to access the accessory.
+ * This may result in a system dialog being displayed to the user
+ * if permission had not already been granted.
+ * Success or failure is returned via the {@link android.app.PendingIntent} pi.
+ * The following extras will be added to pi:
+ * <ul>
+ * <li> {@link #EXTRA_ACCESSORY} containing the accessory passed into this call
+ * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether
+ * permission was granted by the user
+ * </ul>
+ *
+ * @param accessory to request permissions for
+ * @param pi PendingIntent for returning result
+ */
+ public void requestPermission(UsbAccessory accessory, PendingIntent pi) {
+ try {
+ mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in requestPermission", e);
+ }
+ }
+
private static File getFunctionEnableFile(String function) {
return new File("/sys/class/usb_composite/" + function + "/enable");
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index ec5030c..e308c2c 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -423,9 +423,16 @@
/**
* Returns whether the device has an external storage device which is
- * emulated. If true, the device does not have real external storage
- * and certain system services such as the package manager use this
+ * emulated. If true, the device does not have real external storage, and the directory
+ * returned by {@link #getExternalStorageDirectory()} will be allocated using a portion of
+ * the internal storage system.
+ *
+ * <p>Certain system services, such as the package manager, use this
* to determine where to install an application.
+ *
+ * <p>Emulated external storage may also be encrypted - see
+ * {@link android.app.admin.DevicePolicyManager#setStorageEncryption(
+ * android.content.ComponentName, boolean)} for additional details.
*/
public static boolean isExternalStorageEmulated() {
if (mIsExternalStorageEmulated == null) {
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index a1501e6..834dac3 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -139,8 +139,7 @@
* Caches {@code value} for {@code key}. The value is moved to the head of
* the queue.
*
- * @return the previous value mapped by {@code key}. Although that entry is
- * no longer cached, it has not been passed to {@link #entryEvicted}.
+ * @return the previous value mapped by {@code key}.
*/
public final V put(K key, V value) {
if (key == null || value == null) {
@@ -195,15 +194,14 @@
evictionCount++;
}
- entryEvicted(key, value);
+ entryRemoved(true, key, value, null);
}
}
/**
* Removes the entry for {@code key} if it exists.
*
- * @return the previous value mapped by {@code key}. Although that entry is
- * no longer cached, it has not been passed to {@link #entryEvicted}.
+ * @return the previous value mapped by {@code key}.
*/
public final V remove(K key) {
if (key == null) {
@@ -226,16 +224,6 @@
}
/**
- * Calls {@link #entryRemoved}.
- *
- * @deprecated replaced by entryRemoved
- */
- @Deprecated
- protected void entryEvicted(K key, V value) {
- entryRemoved(true, key, value, null);
- }
-
- /**
* Called for entries that have been evicted or removed. This method is
* invoked when a value is evicted to make space, removed by a call to
* {@link #remove}, or replaced by a call to {@link #put}. The default
@@ -291,7 +279,7 @@
}
/**
- * Clear the cache, calling {@link #entryEvicted} on each removed entry.
+ * Clear the cache, calling {@link #entryRemoved} on each removed entry.
*/
public final void evictAll() {
trimToSize(-1); // -1 will evict 0-sized elements
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 9a6a274..fa5479b 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -245,11 +245,12 @@
private static native void nDestroyDisplayList(int displayList);
@Override
- public boolean drawDisplayList(DisplayList displayList) {
- return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
+ public boolean drawDisplayList(DisplayList displayList, Rect dirty) {
+ return nDrawDisplayList(mRenderer,
+ ((GLES20DisplayList) displayList).mNativeDisplayList, dirty);
}
- private static native boolean nDrawDisplayList(int renderer, int displayList);
+ private static native boolean nDrawDisplayList(int renderer, int displayList, Rect dirty);
///////////////////////////////////////////////////////////////////////////
// Hardware layer
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index e6fecc8..cb1003a 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -53,8 +53,13 @@
* Draws the specified display list onto this canvas.
*
* @param displayList The display list to replay.
+ * @param dirty The dirty region to redraw in the next pass, matters only
+ * if this method returns true, can be null.
+ *
+ * @return True if the content of the display list requires another
+ * drawing pass (invalidate()), false otherwise
*/
- abstract boolean drawDisplayList(DisplayList displayList);
+ abstract boolean drawDisplayList(DisplayList displayList, Rect dirty);
/**
* Draws the specified layer onto this canvas.
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index b53aa21..0cf7ae6 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -269,7 +269,7 @@
static EGLDisplay sEglDisplay;
static EGLConfig sEglConfig;
- private static Thread sEglThread;
+ private static Thread sEglThread;
EGLSurface mEglSurface;
@@ -284,6 +284,8 @@
final boolean mTranslucent;
private boolean mDestroyed;
+
+ private final Rect mRedrawClip = new Rect();
GlRenderer(int glVersion, boolean translucent) {
mGlVersion = glVersion;
@@ -606,8 +608,13 @@
DisplayList displayList = view.getDisplayList();
if (displayList != null) {
- if (canvas.drawDisplayList(displayList)) {
- view.invalidate();
+ if (canvas.drawDisplayList(displayList, mRedrawClip)) {
+ if (mRedrawClip.isEmpty() || view.getParent() == null) {
+ view.invalidate();
+ } else {
+ view.getParent().invalidateChild(view, mRedrawClip);
+ }
+ mRedrawClip.setEmpty();
}
} else {
// Shouldn't reach here
@@ -646,8 +653,8 @@
private int checkCurrent() {
// TODO: Don't check the current context when we have one per UI thread
// TODO: Use a threadlocal flag to know whether the surface has changed
- if (sEgl.eglGetCurrentContext() != sEglContext ||
- sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) {
+ if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
+ !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
fallback(true);
Log.e(LOG_TAG, "eglMakeCurrent failed " +
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9f1eef9..f9692da 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2585,7 +2585,7 @@
}
} else {
child.mPrivateFlags &= ~DIRTY_MASK;
- ((HardwareCanvas) canvas).drawDisplayList(displayList);
+ ((HardwareCanvas) canvas).drawDisplayList(displayList, null);
}
}
} else if (cache != null) {
@@ -3680,7 +3680,7 @@
// flag coming from the child that initiated the invalidate
if (view != null) {
if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&
- view.getSolidColor() == 0 && !view.isOpaque()) {
+ view.getSolidColor() == 0) {
opaqueFlag = DIRTY;
}
if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index ab4bfe1..c7a7374 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1237,11 +1237,17 @@
}
}
-
/*package*/ SearchBox getSearchBox() {
return mSearchBox;
}
+ /**
+ * Called by JNI when processing the X-Auto-Login header.
+ */
+ private void autoLogin(String realm, String account, String args) {
+ mCallbackProxy.onReceivedLoginRequest(realm, account, args);
+ }
+
//==========================================================================
// native functions
//==========================================================================
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index c66d701..23fd12d 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -117,6 +117,7 @@
private static final int AUTH_CREDENTIALS = 137;
private static final int SET_INSTALLABLE_WEBAPP = 138;
private static final int NOTIFY_SEARCHBOX_LISTENERS = 139;
+ private static final int AUTO_LOGIN = 140;
// Message triggered by the client to resume execution
private static final int NOTIFY = 200;
@@ -770,7 +771,7 @@
(WebHistoryItem) msg.obj, msg.arg1);
}
break;
- case AUTH_CREDENTIALS:
+ case AUTH_CREDENTIALS: {
String host = msg.getData().getString("host");
String realm = msg.getData().getString("realm");
username = msg.getData().getString("username");
@@ -778,6 +779,7 @@
mWebView.setHttpAuthUsernamePassword(
host, realm, username, password);
break;
+ }
case SET_INSTALLABLE_WEBAPP:
if (mWebChromeClient != null) {
mWebChromeClient.setInstallableWebApp();
@@ -789,6 +791,17 @@
@SuppressWarnings("unchecked")
List<String> suggestions = (List<String>) msg.obj;
searchBox.handleSuggestions(msg.getData().getString("query"), suggestions);
+ break;
+ case AUTO_LOGIN: {
+ if (mWebViewClient != null) {
+ String realm = msg.getData().getString("realm");
+ String account = msg.getData().getString("account");
+ String args = msg.getData().getString("args");
+ mWebViewClient.onReceivedLoginRequest(mWebView, realm,
+ account, args);
+ }
+ break;
+ }
}
}
@@ -1051,6 +1064,20 @@
sendMessage(msg);
}
+ void onReceivedLoginRequest(String realm, String account, String args) {
+ // Do an unsynchronized quick check to avoid posting if no callback has
+ // been set.
+ if (mWebViewClient == null) {
+ return;
+ }
+ Message msg = obtainMessage(AUTO_LOGIN);
+ Bundle bundle = msg.getData();
+ bundle.putString("realm", realm);
+ bundle.putString("account", account);
+ bundle.putString("args", args);
+ sendMessage(msg);
+ }
+
//--------------------------------------------------------------------------
// DownloadListener functions.
//--------------------------------------------------------------------------
diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java
index 2dac7e9..3cb5e24 100644
--- a/core/java/android/webkit/DebugFlags.java
+++ b/core/java/android/webkit/DebugFlags.java
@@ -31,7 +31,7 @@
public static final boolean CACHE_MANAGER = false;
public static final boolean CALLBACK_PROXY = false;
public static final boolean COOKIE_MANAGER = false;
- public static final boolean COOKIE_SYNC_MANAGER = true;
+ public static final boolean COOKIE_SYNC_MANAGER = false;
public static final boolean FRAME_LOADER = false;
public static final boolean J_WEB_CORE_JAVA_BRIDGE = false;// HIGHLY VERBOSE
public static final boolean LOAD_LISTENER = false;
@@ -41,7 +41,7 @@
public static final boolean URL_UTIL = false;
public static final boolean WEB_BACK_FORWARD_LIST = false;
public static final boolean WEB_SETTINGS = false;
- public static final boolean WEB_SYNC_MANAGER = true;
+ public static final boolean WEB_SYNC_MANAGER = false;
public static final boolean WEB_TEXT_VIEW = false;
public static final boolean WEB_VIEW = false;
public static final boolean WEB_VIEW_CORE = false;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f0a3a0f..9b1f157 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -351,7 +351,8 @@
private ZoomManager mZoomManager;
- private Rect mGLRectViewport = new Rect();
+ private final Rect mGLRectViewport = new Rect();
+ private final Rect mViewRectViewport = new Rect();
private boolean mGLViewportEmpty = false;
/**
@@ -3016,7 +3017,8 @@
}
/**
- * Start an ActionMode for finding text in this WebView.
+ * Start an ActionMode for finding text in this WebView. Only works if this
+ * WebView is attached to the view system.
* @param text If non-null, will be the initial text to search for.
* Otherwise, the last String searched for in this WebView will
* be used to start.
@@ -3026,7 +3028,7 @@
*/
public boolean showFindDialog(String text, boolean showIme) {
FindActionModeCallback callback = new FindActionModeCallback(mContext);
- if (startActionMode(callback) == null) {
+ if (getParent() == null || startActionMode(callback) == null) {
// Could not start the action mode, so end Find on page
return false;
}
@@ -4034,15 +4036,10 @@
}
}
- void setBaseLayer(int layer, Rect invalRect, boolean showVisualIndciator) {
+ void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator) {
if (mNativeClass == 0)
return;
- if (invalRect == null) {
- Rect rect = new Rect(0, 0, mContentWidth, mContentHeight);
- nativeSetBaseLayer(layer, rect, showVisualIndciator);
- } else {
- nativeSetBaseLayer(layer, invalRect, showVisualIndciator);
- }
+ nativeSetBaseLayer(layer, invalRegion, showVisualIndicator);
}
private void onZoomAnimationStart() {
@@ -4152,7 +4149,7 @@
if (canvas.isHardwareAccelerated()) {
int functor = nativeGetDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
- getScale(), extras);
+ mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras);
((HardwareCanvas) canvas).callDrawGLFunction(functor);
} else {
DrawFilter df = null;
@@ -5258,6 +5255,7 @@
// Then need to invert the Y axis, just for GL
View rootView = getRootView();
int rootViewHeight = rootView.getHeight();
+ mViewRectViewport.set(mGLRectViewport);
int savedWebViewBottom = mGLRectViewport.bottom;
mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeight();
mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
@@ -5265,7 +5263,8 @@
} else {
mGLViewportEmpty = true;
}
- nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport);
+ nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
+ mGLViewportEmpty ? null : mViewRectViewport);
}
/**
@@ -5567,7 +5566,7 @@
ted.mReprocess = mDeferTouchProcess;
ted.mNativeLayer = nativeScrollableLayer(
contentX, contentY, ted.mNativeLayerRect, null);
- ted.mDontEnqueueResult = true;
+ ted.mSequence = mTouchEventQueue.nextTouchSequence();
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
if (mDeferTouchProcess) {
// still needs to set them for compute deltaX/Y
@@ -5614,7 +5613,7 @@
ted.mReprocess = mDeferTouchProcess;
ted.mNativeLayer = mScrollingLayer;
ted.mNativeLayerRect.set(mScrollingLayerRect);
- ted.mDontEnqueueResult = true;
+ ted.mSequence = mTouchEventQueue.nextTouchSequence();
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
mLastSentTouchTime = eventTime;
if (mDeferTouchProcess) {
@@ -5796,7 +5795,7 @@
ted.mReprocess = mDeferTouchProcess;
ted.mNativeLayer = mScrollingLayer;
ted.mNativeLayerRect.set(mScrollingLayerRect);
- ted.mDontEnqueueResult = true;
+ ted.mSequence = mTouchEventQueue.nextTouchSequence();
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
}
mLastTouchUpTime = eventTime;
@@ -5819,7 +5818,7 @@
ted.mNativeLayer = nativeScrollableLayer(
contentX, contentY,
ted.mNativeLayerRect, null);
- ted.mDontEnqueueResult = true;
+ ted.mSequence = mTouchEventQueue.nextTouchSequence();
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mPreventDefault != PREVENT_DEFAULT_YES){
mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
@@ -6037,7 +6036,7 @@
ted.mAction = MotionEvent.ACTION_CANCEL;
ted.mNativeLayer = nativeScrollableLayer(
x, y, ted.mNativeLayerRect, null);
- ted.mDontEnqueueResult = true;
+ ted.mSequence = mTouchEventQueue.nextTouchSequence();
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
mPreventDefault = PREVENT_DEFAULT_IGNORE;
}
@@ -7521,7 +7520,7 @@
ted.mNativeLayer = nativeScrollableLayer(
ted.mPoints[0].x, ted.mPoints[0].y,
ted.mNativeLayerRect, null);
- ted.mDontEnqueueResult = true;
+ ted.mSequence = mTouchEventQueue.nextTouchSequence();
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mPreventDefault != PREVENT_DEFAULT_YES) {
mTouchMode = TOUCH_DONE_MODE;
@@ -7567,7 +7566,7 @@
case NEW_PICTURE_MSG_ID: {
// called for new content
final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj;
- setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds(),
+ setBaseLayer(draw.mBaseLayer, draw.mInvalRegion,
getSettings().getShowVisualIndicator());
final Point viewSize = draw.mViewSize;
WebViewCore.ViewState viewState = draw.mViewState;
@@ -7737,9 +7736,12 @@
break;
}
TouchEventData ted = (TouchEventData) msg.obj;
- if (!ted.mDontEnqueueResult) {
- mTouchEventQueue.enqueueTouchEvent(ted);
- }
+
+ // WebCore is responding to us; remove pending timeout.
+ // It will be re-posted when needed.
+ removeMessages(PREVENT_DEFAULT_TIMEOUT);
+
+ mTouchEventQueue.enqueueTouchEvent(ted);
break;
case REQUEST_KEYBOARD:
@@ -8531,8 +8533,9 @@
boolean splitIfNeeded);
private native void nativeDumpDisplayTree(String urlOrNull);
private native boolean nativeEvaluateLayersAnimations();
- private native int nativeGetDrawGLFunction(Rect rect, float scale, int extras);
- private native void nativeUpdateDrawGLFunction(Rect rect);
+ private native int nativeGetDrawGLFunction(Rect rect, Rect viewRect,
+ float scale, int extras);
+ private native void nativeUpdateDrawGLFunction(Rect rect, Rect viewRect);
private native boolean nativeDrawGL(Rect rect, float scale, int extras);
private native void nativeExtendSelection(int x, int y);
private native int nativeFindAll(String findLower, String findUpper,
@@ -8608,7 +8611,7 @@
private native void nativeSetFindIsEmpty();
private native void nativeSetFindIsUp(boolean isUp);
private native void nativeSetHeightCanMeasure(boolean measure);
- private native void nativeSetBaseLayer(int layer, Rect invalRect,
+ private native void nativeSetBaseLayer(int layer, Region invalRegion,
boolean showVisualIndicator);
private native void nativeShowCursorTimed();
private native void nativeReplaceBaseContent(int content);
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index db605de..65026a5 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -256,4 +256,18 @@
*/
public void onScaleChanged(WebView view, float oldScale, float newScale) {
}
+
+ /**
+ * Notify the host application that a request to automatically log in the
+ * user has been processed.
+ * @param view The WebView requesting the login.
+ * @param realm The account realm used to look up accounts.
+ * @param account An optional account. If not null, the account should be
+ * checked against accounts on the device. If it is a valid
+ * account, it should be used to log in the user.
+ * @param args Authenticator specific arguments used to log in the user.
+ */
+ public void onReceivedLoginRequest(WebView view, String realm,
+ String account, String args) {
+ }
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index f367b93..b920a30 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -827,7 +827,6 @@
Rect mNativeLayerRect = new Rect();
long mSequence;
boolean mNativeResult;
- boolean mDontEnqueueResult;
}
static class GeolocationPermissionsData {
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index f27ced8..942425af 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -16,6 +16,9 @@
package android.webkit;
+import java.util.LinkedList;
+import java.util.Queue;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
@@ -23,6 +26,7 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.SystemClock;
+import android.util.FloatMath;
import android.util.Log;
import android.view.ScaleGestureDetector;
import android.view.View;
@@ -112,6 +116,24 @@
private float mZoomCenterY;
/*
+ * Similar to mZoomCenterX(Y), these track the focus point of the scale
+ * gesture. The difference is these get updated every time when onScale is
+ * invoked no matter if a zooming really happens.
+ */
+ private float mFocusX;
+ private float mFocusY;
+
+ /*
+ * mFocusMovement keeps track of the total movement that the focus point
+ * has been through. Comparing to the difference of mCurrlen and mPrevLen,
+ * it determines if the gesture is for panning or zooming or both.
+ */
+ private static final int FOCUS_QUEUE_SIZE = 5;
+ private float mFocusMovementSum;
+ private Queue<Float> mFocusMovementQueue;
+
+
+ /*
* These values represent the point around which the screen should be
* centered after zooming. In other words it is used to determine the center
* point of the visible document after the page has finished zooming. This
@@ -196,6 +218,8 @@
* viewport size is.
*/
setZoomOverviewWidth(WebView.DEFAULT_VIEWPORT_WIDTH);
+
+ mFocusMovementQueue = new LinkedList<Float>();
}
/**
@@ -715,10 +739,11 @@
}
private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener {
-
public boolean onScaleBegin(ScaleGestureDetector detector) {
mInitialZoomOverview = false;
dismissZoomPicker();
+ mFocusMovementSum = 0;
+ mFocusMovementQueue.clear();
mWebView.mViewManager.startZoom();
mWebView.onPinchToZoomAnimationStart();
return true;
@@ -729,6 +754,29 @@
float scale = Math.max(
computeScaleWithLimits(detector.getScaleFactor() * mActualScale),
getZoomOverviewScale());
+
+ float prevFocusX = mFocusX;
+ float prevFocusY = mFocusY;
+ mFocusX = detector.getFocusX();
+ mFocusY = detector.getFocusY();
+ float focusDelta = (prevFocusX == 0 && prevFocusY == 0) ? 0 :
+ FloatMath.sqrt((mFocusX - prevFocusX) * (mFocusX - prevFocusX)
+ + (mFocusY - prevFocusY) * (mFocusY - prevFocusY));
+ mFocusMovementSum += focusDelta;
+ mFocusMovementQueue.add(focusDelta);
+ if (mFocusMovementQueue.size() > FOCUS_QUEUE_SIZE) {
+ mFocusMovementSum -= mFocusMovementQueue.remove();
+ }
+ float deltaSpan = Math.abs(detector.getCurrentSpan() - detector.getPreviousSpan());
+
+ // If the user moves the fingers but keeps the same distance between them,
+ // we should do panning only.
+ if (mFocusMovementSum > deltaSpan) {
+ mFocusMovementSum = 0;
+ mFocusMovementQueue.clear();
+ return true;
+ }
+
if (mPinchToZoomAnimating || willScaleTriggerZoom(scale)) {
mPinchToZoomAnimating = true;
// limit the scale change per step
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index d92588cb..17b3bda 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -477,8 +477,7 @@
break;
case MotionEvent.ACTION_POINTER_DOWN: {
final int index = ev.getActionIndex();
- final float x = ev.getX(index);
- mLastMotionX = x;
+ mLastMotionX = ev.getX(index);
mActivePointerId = ev.getPointerId(index);
break;
}
@@ -1446,6 +1445,7 @@
super.setOverScrollMode(mode);
}
+ @SuppressWarnings({"SuspiciousNameCombination"})
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 9002b1d..72b70bc 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1039,7 +1039,7 @@
*
* @return true if the popup is translated upwards to fit on screen
*/
- boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
+ private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
int xoff, int yoff) {
anchor.getLocationInWindow(mDrawingLocation);
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 2d164fd..6088654 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -83,6 +83,7 @@
private CursorAdapter mSuggestionsAdapter;
private View mSearchButton;
private View mSubmitButton;
+ private View mSearchPlate;
private View mSubmitArea;
private ImageView mCloseButton;
private View mSearchEditFrame;
@@ -190,6 +191,7 @@
mQueryTextView.setSearchView(this);
mSearchEditFrame = findViewById(R.id.search_edit_frame);
+ mSearchPlate = findViewById(R.id.search_plate);
mSubmitArea = findViewById(R.id.submit_area);
mSubmitButton = findViewById(R.id.search_go_btn);
mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
@@ -258,6 +260,7 @@
mSearchable = searchable;
if (mSearchable != null) {
updateSearchAutoComplete();
+ updateQueryHint();
}
// Cache the voice search capability
mVoiceButtonEnabled = hasVoiceSearch();
@@ -575,19 +578,19 @@
}
private void updateSubmitButton(boolean hasText) {
- mSubmitButton.setVisibility(
- isSubmitAreaEnabled() ? (hasText ? VISIBLE : INVISIBLE) : GONE);
+ int visibility = GONE;
+ if (isSubmitAreaEnabled() && hasFocus() && (hasText || !mVoiceButtonEnabled)) {
+ visibility = VISIBLE;
+ }
+ mSubmitButton.setVisibility(visibility);
}
private void updateSubmitArea() {
int visibility = GONE;
- if (isSubmitAreaEnabled()) {
- if (mSubmitButton.getVisibility() == VISIBLE
- || mVoiceButton.getVisibility() == VISIBLE) {
- visibility = VISIBLE;
- } else {
- visibility = INVISIBLE;
- }
+ if (isSubmitAreaEnabled()
+ && (mSubmitButton.getVisibility() == VISIBLE
+ || mVoiceButton.getVisibility() == VISIBLE)) {
+ visibility = VISIBLE;
}
mSubmitArea.setVisibility(visibility);
}
@@ -601,6 +604,11 @@
mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
}
+ private void updateFocusedState(boolean focused) {
+ mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
+ mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
+ }
+
private void setImeVisibility(boolean visible) {
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -851,16 +859,11 @@
* Update the visibility of the voice button. There are actually two voice search modes,
* either of which will activate the button.
* @param empty whether the search query text field is empty. If it is, then the other
- * criteria apply to make the voice button visible. Otherwise the voice button will not
- * be visible - i.e., if the user has typed a query, remove the voice button.
+ * criteria apply to make the voice button visible.
*/
private void updateVoiceButton(boolean empty) {
- // If the voice button is to be visible, show it
- // Else, make it gone if the submit button is enabled, otherwise invisible to
- // avoid losing the real-estate
- int visibility = mSubmitButtonEnabled ? GONE : INVISIBLE;
-
- if (mVoiceButtonEnabled && !isIconified() && empty) {
+ int visibility = GONE;
+ if (mVoiceButtonEnabled && !isIconified() && (empty || !mSubmitButtonEnabled)) {
visibility = VISIBLE;
mSubmitButton.setVisibility(GONE);
}
@@ -958,7 +961,8 @@
}
void onTextFocusChanged() {
- updateCloseButton();
+ updateViewsVisibility(isIconified());
+ updateFocusedState(mQueryTextView.hasFocus());
}
private boolean onItemClicked(int position, int actionKey, String actionMsg) {
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index bab469b..21c61bd 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -531,6 +531,8 @@
@Override
protected void dispatchDraw(Canvas canvas) {
+ boolean expandClipRegion = false;
+
canvas.getClipBounds(stackInvalidateRect);
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -540,12 +542,22 @@
child.getAlpha() == 0f || child.getVisibility() != VISIBLE) {
lp.resetInvalidateRect();
}
- stackInvalidateRect.union(lp.getInvalidateRect());
+ Rect childInvalidateRect = lp.getInvalidateRect();
+ if (!childInvalidateRect.isEmpty()) {
+ expandClipRegion = true;
+ stackInvalidateRect.union(childInvalidateRect);
+ }
}
- canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipRect(stackInvalidateRect, Region.Op.UNION);
- super.dispatchDraw(canvas);
- canvas.restore();
+
+ // We only expand the clip bounds if necessary.
+ if (expandClipRegion) {
+ canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipRect(stackInvalidateRect, Region.Op.UNION);
+ super.dispatchDraw(canvas);
+ canvas.restore();
+ } else {
+ super.dispatchDraw(canvas);
+ }
}
private void onLayout() {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 09c1ac5..13b9285f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4498,8 +4498,6 @@
*/
canvas.restore();
-
- updateCursorControllerPositions();
}
private void updateCursorsPositions() {
@@ -4557,15 +4555,7 @@
* @hide
*/
protected void updateCursorControllerPositions() {
- // No need to create the controllers if they were not already
- if (mInsertionPointCursorController != null &&
- mInsertionPointCursorController.isShowing()) {
- mInsertionPointCursorController.updatePosition();
- }
- if (mSelectionModifierCursorController != null &&
- mSelectionModifierCursorController.isShowing()) {
- mSelectionModifierCursorController.updatePosition();
- }
+ // TODO remove
}
@Override
@@ -7356,14 +7346,9 @@
}
if (isTextEditable() || mTextIsSelectable) {
- if (mScrollX != oldScrollX || mScrollY != oldScrollY) {
+ if (mScrollX != oldScrollX || mScrollY != oldScrollY) { // TODO remove
// 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();
- }
+ hideInsertionPointCursorController(); // TODO any motion should hide it
}
if (touchIsFinished) {
@@ -7373,7 +7358,6 @@
handled |= imm != null && imm.showSoftInput(this, 0);
}
-
boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect();
if (!selectAllGotFocus && hasSelection()) {
startSelectionActionMode();
@@ -8653,26 +8637,31 @@
}
}
- private class HandleView extends View implements ViewTreeObserver.OnScrollChangedListener {
+ private class HandleView extends View implements ViewTreeObserver.OnPreDrawListener {
private Drawable mDrawable;
- private final ScrollingPopupWindow mContainer;
- private int mPositionX;
- private int mPositionY;
+ private final PopupWindow mContainer;
+ // Position with respect to the parent TextView
+ private int mPositionX, mPositionY;
private final CursorController mController;
private boolean mIsDragging;
- private float mTouchToWindowOffsetX;
- private float mTouchToWindowOffsetY;
+ // Offset from touch position to mPosition
+ private float mTouchToWindowOffsetX, mTouchToWindowOffsetY;
private float mHotspotX;
// Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up
private float mTouchOffsetY;
// Where the touch position should be on the handle to ensure a maximum cursor visibility
private float mIdealVerticalOffset;
- private int mLastParentX;
- private int mLastParentY;
+ // Parent's (TextView) position in window
+ private int mLastParentX, mLastParentY;
private float mDownPositionX, mDownPositionY;
+ // PopupWindow container absolute position with respect to the enclosing window
private int mContainerPositionX, mContainerPositionY;
- private long mTouchTimer;
+ // Visible or not (scrolled off screen), whether or not this handle should be visible
+ private boolean mIsActive = false;
+ // The insertion handle can have an associated PastePopupMenu
private boolean mIsInsertionHandle = false;
+ // Used to detect taps on the insertion handle, which will affect the PastePopupMenu
+ private long mTouchTimer;
private PastePopupMenu mPastePopupWindow;
// Touch-up filter: number of previous positions remembered
@@ -8684,12 +8673,12 @@
private int mPreviousOffsetIndex = 0;
private int mNumberPreviousOffsets = 0;
- public void startTouchUpFilter(int offset) {
+ private void startTouchUpFilter(int offset) {
mNumberPreviousOffsets = 0;
addPositionToTouchUpFilter(offset);
}
- public void addPositionToTouchUpFilter(int offset) {
+ private void addPositionToTouchUpFilter(int offset) {
if (mNumberPreviousOffsets > 0 &&
mPreviousOffsets[mPreviousOffsetIndex] == offset) {
// Make sure only actual changes of position are recorded.
@@ -8702,7 +8691,7 @@
mNumberPreviousOffsets++;
}
- public void filterOnTouchUp() {
+ private void filterOnTouchUp() {
final long now = SystemClock.uptimeMillis();
int i = 0;
int index = mPreviousOffsetIndex;
@@ -8725,16 +8714,17 @@
public HandleView(CursorController controller, int pos) {
super(TextView.this.mContext);
mController = controller;
- mContainer = new ScrollingPopupWindow(TextView.this.mContext, null,
+ mContainer = new PopupWindow(TextView.this.mContext, null,
com.android.internal.R.attr.textSelectHandleWindowStyle);
mContainer.setSplitTouchEnabled(true);
mContainer.setClippingEnabled(false);
mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+ mContainer.setContentView(this);
- setOrientation(pos);
+ setPosition(pos);
}
- public void setOrientation(int pos) {
+ private void setPosition(int pos) {
int handleWidth;
switch (pos) {
case LEFT: {
@@ -8774,38 +8764,48 @@
}
final int handleHeight = mDrawable.getIntrinsicHeight();
-
mTouchOffsetY = -0.3f * handleHeight;
mIdealVerticalOffset = 0.7f * handleHeight;
+
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(mDrawable.getIntrinsicWidth(),
- mDrawable.getIntrinsicHeight());
+ setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
}
public void show() {
- if (!isPositionVisible()) {
- hide();
- return;
- }
- mContainer.setContentView(this);
- mContainerPositionX = mPositionX;
- mContainerPositionY = mPositionY - TextView.this.getHeight();
- mContainer.showAsDropDown(TextView.this, mContainerPositionX, mContainerPositionY);
+ updateContainerPosition();
+ if (isShowing()) {
+ mContainer.update(mContainerPositionX, mContainerPositionY,
+ mRight - mLeft, mBottom - mTop);
- // Hide paste view when handle is moved on screen.
+ hidePastePopupWindow();
+ } else {
+ mContainer.showAtLocation(TextView.this, 0,
+ mContainerPositionX, mContainerPositionY);
+
+ mIsActive = true;
+
+ ViewTreeObserver vto = TextView.this.getViewTreeObserver();
+ vto.addOnPreDrawListener(this);
+ }
+ }
+
+ private void dismiss() {
+ mIsDragging = false;
+ mContainer.dismiss();
hidePastePopupWindow();
}
public void hide() {
- mIsDragging = false;
- mContainer.dismiss();
- hidePastePopupWindow();
+ dismiss();
+
+ mIsActive = false;
+
ViewTreeObserver vto = TextView.this.getViewTreeObserver();
- vto.removeOnScrollChangedListener(this);
+ vto.removeOnPreDrawListener(this);
}
public boolean isShowing() {
@@ -8856,44 +8856,59 @@
private void moveTo(int x, int y) {
mPositionX = x - TextView.this.mScrollX;
mPositionY = y - TextView.this.mScrollY;
- if (isPositionVisible()) {
- int[] coords = null;
- if (mContainer.isShowing()) {
- final int containerPositionX = mPositionX;
- final int containerPositionY = mPositionY - TextView.this.getHeight();
- if (containerPositionX != mContainerPositionX ||
- containerPositionY != mContainerPositionY) {
- mContainerPositionX = containerPositionX;
- mContainerPositionY = containerPositionY;
+ if (mIsDragging) {
+ TextView.this.getLocationInWindow(mTempCoords);
+ if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) {
+ mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX;
+ mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY;
+ mLastParentX = mTempCoords[0];
+ mLastParentY = mTempCoords[1];
+ }
+ // Hide paste popup window as soon as the handle is dragged.
+ hidePastePopupWindow();
+ }
+ }
- mContainer.update(TextView.this, mContainerPositionX, mContainerPositionY,
- mRight - mLeft, mBottom - mTop);
+ /**
+ * Updates the global container's position.
+ * @return whether or not the position has actually changed
+ */
+ private boolean updateContainerPosition() {
+ // TODO Prevent this using different HandleView subclasses
+ mController.updateOffset(this, mController.getCurrentOffset(this));
+ TextView.this.getLocationInWindow(mTempCoords);
+ final int containerPositionX = mTempCoords[0] + mPositionX;
+ final int containerPositionY = mTempCoords[1] + mPositionY;
- // Hide paste popup window as soon as a scroll occurs.
- hidePastePopupWindow();
+ if (containerPositionX != mContainerPositionX ||
+ containerPositionY != mContainerPositionY) {
+ mContainerPositionX = containerPositionX;
+ mContainerPositionY = containerPositionY;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean onPreDraw() {
+ if (updateContainerPosition()) {
+ if (isPositionVisible()) {
+ mContainer.update(mContainerPositionX, mContainerPositionY,
+ mRight - mLeft, mBottom - mTop);
+
+ if (mIsActive && !isShowing()) {
+ show();
}
} else {
- show();
+ if (isShowing()) {
+ dismiss();
+ }
}
- if (mIsDragging) {
- if (coords == null) {
- coords = mTempCoords;
- TextView.this.getLocationInWindow(coords);
- }
- if (coords[0] != mLastParentX || coords[1] != mLastParentY) {
- mTouchToWindowOffsetX += coords[0] - mLastParentX;
- mTouchToWindowOffsetY += coords[1] - mLastParentY;
- mLastParentX = coords[0];
- mLastParentY = coords[1];
- }
- // Hide paste popup window as soon as the handle is dragged.
- hidePastePopupWindow();
- }
- } else {
- hide();
+ // Hide paste popup as soon as the view is scrolled or moved
+ hidePastePopupWindow();
}
+ return true;
}
@Override
@@ -8979,7 +8994,7 @@
return mIsDragging;
}
- void positionAtCursor(final int offset) {
+ void positionAtCursor(int offset) {
addPositionToTouchUpFilter(offset);
final int width = mDrawable.getIntrinsicWidth();
final int height = mDrawable.getIntrinsicHeight();
@@ -9013,50 +9028,6 @@
mPastePopupWindow.hide();
}
}
-
- /**
- * A popup window, attached to a view, and that listens to scroll events in its anchors'
- * view hierarchy, so that it is automatically moved on such events.
- */
- private class ScrollingPopupWindow extends PopupWindow {
-
- private int[] mDrawingLocations = new int[2];
-
- public ScrollingPopupWindow(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
- int xoff, int yoff) {
- anchor.getLocationInWindow(mDrawingLocations);
- p.x = mDrawingLocations[0] + xoff;
- p.y = mDrawingLocations[1] + anchor.getHeight() + yoff;
-
- // Hide paste popup as soon as the view is scrolled.
- hidePastePopupWindow();
-
- if (!isPositionVisible()) {
- dismiss();
- onHandleBecomeInvisible();
- }
-
- return false;
- }
- }
-
- public void onScrollChanged() {
- if (isPositionVisible()) {
- show();
- ViewTreeObserver vto = TextView.this.getViewTreeObserver();
- vto.removeOnScrollChangedListener(this);
- }
- }
-
- public void onHandleBecomeInvisible() {
- ViewTreeObserver vto = TextView.this.getViewTreeObserver();
- vto.addOnScrollChangedListener(this);
- }
}
private class InsertionPointCursorController implements CursorController {
@@ -9074,7 +9045,7 @@
}
public void show(int delayBeforePaste) {
- updatePosition();
+ getHandle().show();
hideDelayed();
removePastePopupCallback();
final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
@@ -9213,7 +9184,6 @@
if (mEndHandle == null) mEndHandle = new HandleView(this, HandleView.RIGHT);
mIsShowing = true;
- updatePosition();
mStartHandle.show();
mEndHandle.show();
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index a41b348..586ba87 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -43,6 +43,7 @@
import android.view.ViewParent;
import android.view.Window;
import android.widget.AdapterView;
+import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -957,4 +958,60 @@
}
}
}
+
+ private static class HomeView extends FrameLayout {
+ private View mUpView;
+ private View mIconView;
+
+ public HomeView(Context context) {
+ this(context, null);
+ }
+
+ public HomeView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mUpView = findViewById(com.android.internal.R.id.up);
+ mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
+ int width = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin;
+ int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
+ measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
+ final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
+ width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
+ height = Math.max(height,
+ iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int vCenter = (b - t) / 2;
+ int width = r - l;
+ if (mUpView.getVisibility() != GONE) {
+ final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
+ final int upHeight = mUpView.getMeasuredHeight();
+ final int upWidth = mUpView.getMeasuredWidth();
+ final int upTop = t + vCenter - upHeight / 2;
+ mUpView.layout(l, upTop, l + upWidth, upTop + upHeight);
+ final int upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
+ width -= upOffset;
+ l += upOffset;
+ }
+ final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
+ final int iconHeight = mIconView.getMeasuredHeight();
+ final int iconWidth = mIconView.getMeasuredWidth();
+ final int hCenter = (r - l) / 2;
+ final int iconLeft = l + iconLp.leftMargin + hCenter - iconWidth / 2;
+ final int iconTop = t + iconLp.topMargin + vCenter - iconHeight / 2;
+ mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
+ }
+ }
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 7a609a5..a78f660 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -35,7 +35,6 @@
#include <DisplayListRenderer.h>
#include <LayerRenderer.h>
-#include <OpenGLDebugRenderer.h>
#include <OpenGLRenderer.h>
#include <SkiaShader.h>
#include <SkiaColorFilter.h>
@@ -60,7 +59,6 @@
// Debug
#define DEBUG_RENDERER 0
-#define PROFILE_RENDERER 0
// Debug
#if DEBUG_RENDERER
@@ -99,11 +97,7 @@
static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
RENDERER_LOGD("Create OpenGLRenderer");
-#if PROFILE_RENDERER
- return new OpenGLDebugRenderer;
-#else
return new OpenGLRenderer;
-#endif
}
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
@@ -139,7 +133,8 @@
static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, Functor *functor) {
- return renderer->callDrawGLFunction(functor);
+ android::uirenderer::Rect dirty;
+ return renderer->callDrawGLFunction(functor, dirty);
}
// ----------------------------------------------------------------------------
@@ -503,8 +498,14 @@
}
static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
- jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) {
- return renderer->drawDisplayList(displayList);
+ jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, jobject dirty) {
+ android::uirenderer::Rect bounds;
+ bool redraw = renderer->drawDisplayList(displayList, bounds);
+ if (redraw && dirty != NULL) {
+ env->CallVoidMethod(dirty, gRectClassInfo.set,
+ int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
+ }
+ return redraw;
}
// ----------------------------------------------------------------------------
@@ -663,7 +664,8 @@
{ "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
{ "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
- { "nDrawDisplayList", "(II)Z", (void*) android_view_GLES20Canvas_drawDisplayList },
+ { "nDrawDisplayList", "(IILandroid/graphics/Rect;)Z",
+ (void*) android_view_GLES20Canvas_drawDisplayList },
{ "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
{ "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0ad174f..c684e7e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1379,12 +1379,6 @@
android:excludeFromRecents="true">
</activity>
- <activity android:name="com.android.server.usb.UsbResolverActivity"
- android:theme="@style/Theme.Holo.Dialog.Alert"
- android:finishOnCloseSystemDialogs="true"
- android:excludeFromRecents="true">
- </activity>
-
<service android:name="com.android.server.LoadAverageService"
android:exported="true" />
diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png
index b9435b6..ae77fa0 100644
--- a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png
index 477d820..c6bdfcc 100644
--- a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png
index b9435b6..ae77fa0 100644
--- a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png
index 477d820..c6bdfcc 100644
--- a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png
Binary files differ
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index 7867577..c82f91d 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -14,14 +14,14 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:background="?android:attr/selectableItemBackground"
- android:orientation="horizontal">
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.internal.widget.ActionBarView$HomeView"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="?android:attr/selectableItemBackground" >
<ImageView android:id="@android:id/up"
android:src="?android:attr/homeAsUpIndicator"
- android:layout_gravity="top|left"
+ android:layout_gravity="center_vertical|left"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -33,4 +33,4 @@
android:paddingRight="16dip"
android:layout_gravity="center"
android:scaleType="center" />
-</LinearLayout>
+</view>
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 93b6deb..c52b73f 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -54,6 +54,10 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
+ android:layout_marginLeft="4dip"
+ android:layout_marginRight="4dip"
+ android:layout_marginTop="4dip"
+ android:layout_marginBottom="4dip"
android:orientation="horizontal">
<!-- Inner layout contains the app icon, button(s) and EditText -->
diff --git a/core/res/res/raw-xlarge/incognito_mode_start_page.html b/core/res/res/raw-xlarge/incognito_mode_start_page.html
new file mode 100644
index 0000000..492658d
--- /dev/null
+++ b/core/res/res/raw-xlarge/incognito_mode_start_page.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
+ <title>New incognito tab</title>
+ </head>
+ <body>
+ <p><strong>You've gone incognito</strong>. Pages you view in this tab
+ won't appear in your browser history or search history, and they won't
+ leave other traces, like cookies, on your device after you close the
+ incognito tab. Any files you download or bookmarks you create will be
+ preserved, however.</p>
+
+ <p><strong>Going incognito doesn't affect the behavior of other people,
+ servers, or software. Be wary of:</strong></p>
+
+ <ul>
+ <li>Websites that collect or share information about you</li>
+ <li>Internet service providers or employers that track the pages you visit</li>
+ <li>Malicious software that tracks your keystrokes in exchange for free smileys</li>
+ <li>Surveillance by secret agents</li>
+ <li>People standing behind you</li>
+ </ul>
+ </body>
+</html>
diff --git a/core/tests/coretests/src/android/util/LruCacheTest.java b/core/tests/coretests/src/android/util/LruCacheTest.java
index 7e46e26..5a97158 100644
--- a/core/tests/coretests/src/android/util/LruCacheTest.java
+++ b/core/tests/coretests/src/android/util/LruCacheTest.java
@@ -183,20 +183,15 @@
* Replacing the value for a key doesn't cause an eviction but it does bring
* the replaced entry to the front of the queue.
*/
- public void testPutDoesNotCauseEviction() {
- final List<String> evictionLog = new ArrayList<String>();
- List<String> expectedEvictionLog = new ArrayList<String>();
- LruCache<String, String> cache = new LruCache<String, String>(3) {
- @Override protected void entryEvicted(String key, String value) {
- evictionLog.add(key + "=" + value);
- }
- };
+ public void testPutCauseEviction() {
+ List<String> log = new ArrayList<String>();
+ LruCache<String, String> cache = newRemovalLogCache(log);
cache.put("a", "A");
cache.put("b", "B");
cache.put("c", "C");
cache.put("b", "B2");
- assertEquals(expectedEvictionLog, evictionLog);
+ assertEquals(Arrays.asList("b=B>B2"), log);
assertSnapshot(cache, "a", "A", "c", "C", "b", "B2");
}
diff --git a/docs/html/images/avd-manager.png b/docs/html/images/avd-manager.png
index 69ce972..c33d8a8 100644
--- a/docs/html/images/avd-manager.png
+++ b/docs/html/images/avd-manager.png
Binary files differ
diff --git a/docs/html/images/billing_package.png b/docs/html/images/billing_package.png
old mode 100755
new mode 100644
index ec04c2d..951e117
--- a/docs/html/images/billing_package.png
+++ b/docs/html/images/billing_package.png
Binary files differ
diff --git a/docs/html/images/developing/adt-props-isLib.png b/docs/html/images/developing/adt-props-isLib.png
index 18bdb33..49c9111 100644
--- a/docs/html/images/developing/adt-props-isLib.png
+++ b/docs/html/images/developing/adt-props-isLib.png
Binary files differ
diff --git a/docs/html/images/developing/adt-props-libRef.png b/docs/html/images/developing/adt-props-libRef.png
index e61df51..73bccbd 100644
--- a/docs/html/images/developing/adt-props-libRef.png
+++ b/docs/html/images/developing/adt-props-libRef.png
Binary files differ
diff --git a/docs/html/images/licensing_add_library.png b/docs/html/images/licensing_add_library.png
index 90b4435..3bbe6d5 100644
--- a/docs/html/images/licensing_add_library.png
+++ b/docs/html/images/licensing_add_library.png
Binary files differ
diff --git a/docs/html/images/licensing_gapis_8.png b/docs/html/images/licensing_gapis_8.png
index 43ad262..480d989 100644
--- a/docs/html/images/licensing_gapis_8.png
+++ b/docs/html/images/licensing_gapis_8.png
Binary files differ
diff --git a/docs/html/images/licensing_package.png b/docs/html/images/licensing_package.png
index 5da5632..eb2c5cf 100644
--- a/docs/html/images/licensing_package.png
+++ b/docs/html/images/licensing_package.png
Binary files differ
diff --git a/include/utils/Functor.h b/include/utils/Functor.h
index 3955bc3..565f4a3 100644
--- a/include/utils/Functor.h
+++ b/include/utils/Functor.h
@@ -26,6 +26,7 @@
Functor() {}
virtual ~Functor() {}
virtual status_t operator ()() { return true; }
+ virtual status_t operator ()(float* data, uint32_t len) { return true; }
};
}; // namespace android
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 38e0848..f4a0161 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -15,7 +15,6 @@
LayerCache.cpp \
LayerRenderer.cpp \
Matrix.cpp \
- OpenGLDebugRenderer.cpp \
OpenGLRenderer.cpp \
Patch.cpp \
PatchCache.cpp \
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index d5d2ba0..737fa02 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -166,7 +166,7 @@
void DisplayList::init() {
}
-bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
+bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
bool needsInvalidate = false;
TextContainer text;
mReader.rewind();
@@ -189,7 +189,7 @@
case DrawGLFunction: {
Functor *functor = (Functor *) getInt();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
- needsInvalidate |= renderer.callDrawGLFunction(functor);
+ needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
}
break;
case Save: {
@@ -287,7 +287,7 @@
DisplayList* displayList = getDisplayList();
DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op],
displayList, level + 1);
- needsInvalidate |= renderer.drawDisplayList(displayList, level + 1);
+ needsInvalidate |= renderer.drawDisplayList(displayList, dirty, level + 1);
}
break;
case DrawLayer: {
@@ -589,7 +589,8 @@
void DisplayListRenderer::resume() {
}
-bool DisplayListRenderer::callDrawGLFunction(Functor *functor) {
+bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
+ // Ignore dirty during recording, it matters only when we replay
addOp(DisplayList::DrawGLFunction);
addInt((int) functor);
return false; // No invalidate needed at record-time
@@ -673,7 +674,9 @@
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
}
-bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
+ // dirty is an out parameter and should not be recorded,
+ // it matters only when replaying the display list
addOp(DisplayList::DrawDisplayList);
addDisplayList(displayList);
return false;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index e8f189d..f24545d 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -103,7 +103,7 @@
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
- bool replay(OpenGLRenderer& renderer, uint32_t level = 0);
+ bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
private:
void init();
@@ -214,7 +214,7 @@
void prepareDirty(float left, float top, float right, float bottom, bool opaque);
void finish();
- bool callDrawGLFunction(Functor *functor);
+ bool callDrawGLFunction(Functor *functor, Rect& dirty);
void interrupt();
void resume();
@@ -238,7 +238,7 @@
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+ bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
deleted file mode 100644
index 05870bb..0000000
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ /dev/null
@@ -1,156 +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.
- */
-
-#define LOG_TAG "OpenGLRenderer"
-
-#include <utils/StopWatch.h>
-
-#include "OpenGLDebugRenderer.h"
-
-namespace android {
-namespace uirenderer {
-
-void OpenGLDebugRenderer::prepareDirty(float left, float top,
- float right, float bottom, bool opaque) {
- mPrimitivesCount = 0;
- LOGD("========= Frame start =========");
- OpenGLRenderer::prepareDirty(left, top, right, bottom, opaque);
-}
-
-void OpenGLDebugRenderer::finish() {
- LOGD("========= Frame end =========");
- LOGD("Primitives draw count = %d", mPrimitivesCount);
- OpenGLRenderer::finish();
-}
-
-void OpenGLDebugRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
- mPrimitivesCount++;
- StopWatch w("composeLayer");
- return OpenGLRenderer::composeLayer(current, previous);
-}
-
-int OpenGLDebugRenderer::saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags) {
- mPrimitivesCount++;
- StopWatch w("saveLayer");
- return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
-}
-
-bool OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
- mPrimitivesCount++;
- StopWatch w("drawDisplayList");
- return OpenGLRenderer::drawDisplayList(displayList);
-}
-
-void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawLayer");
- OpenGLRenderer::drawLayer(layer, x, y, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawBitmap");
- OpenGLRenderer::drawBitmap(bitmap, left, top, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawBitmapMatrix");
- OpenGLRenderer::drawBitmap(bitmap, matrix, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawBitmapRect");
- OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
- dstLeft, dstTop, dstRight, dstBottom, paint);
-}
-
-void OpenGLDebugRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
- const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawPatch");
- OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
- left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawColor(int color, SkXfermode::Mode mode) {
- mPrimitivesCount++;
- StopWatch w("drawColor");
- OpenGLRenderer::drawColor(color, mode);
-}
-
-void OpenGLDebugRenderer::drawRect(float left, float top, float right, float bottom,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawRect");
- OpenGLRenderer::drawRect(left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawRoundRect");
- OpenGLRenderer::drawRoundRect(left, top, right, bottom, rx, ry, paint);
-}
-
-void OpenGLDebugRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawCircle");
- OpenGLRenderer::drawCircle(x, y, radius, paint);
-}
-
-void OpenGLDebugRenderer::drawOval(float left, float top, float right, float bottom,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawOval");
- OpenGLRenderer::drawOval(left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawArc");
- OpenGLRenderer::drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
-}
-
-void OpenGLDebugRenderer::drawPath(SkPath* path, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawPath");
- OpenGLRenderer::drawPath(path, paint);
-}
-
-void OpenGLDebugRenderer::drawLines(float* points, int count, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawLines");
- OpenGLRenderer::drawLines(points, count, paint);
-}
-
-void OpenGLDebugRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawText");
- OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint);
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
deleted file mode 100644
index 1a18a67..0000000
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
-#define ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
-
-#include "OpenGLRenderer.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Renderer
-///////////////////////////////////////////////////////////////////////////////
-
-class OpenGLDebugRenderer: public OpenGLRenderer {
-public:
- OpenGLDebugRenderer(): mPrimitivesCount(0) {
- }
-
- ~OpenGLDebugRenderer() {
- }
-
- void prepareDirty(float left, float top, float right, float bottom, bool opaque);
- void finish();
-
- int saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags);
-
- bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
- void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, SkPaint* paint);
- void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
- const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, SkPaint* paint);
- void drawColor(int color, SkXfermode::Mode mode);
- void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
- void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, SkPaint* paint);
- void drawCircle(float x, float y, float radius, SkPaint* paint);
- void drawOval(float left, float top, float right, float bottom, SkPaint* paint);
- void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
- void drawPath(SkPath* path, SkPaint* paint);
- void drawLines(float* points, int count, SkPaint* paint);
- void drawText(const char* text, int bytesCount, int count, float x, float y,
- SkPaint* paint);
-
-protected:
- void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);
-
-private:
- uint32_t mPrimitivesCount;
-
-}; // class OpenGLDebugRenderer
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dfca7eb..1f65201 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -210,7 +210,7 @@
glBlendEquation(GL_FUNC_ADD);
}
-bool OpenGLRenderer::callDrawGLFunction(Functor *functor) {
+bool OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
interrupt();
if (mDirtyClip) {
setScissorFromClip();
@@ -226,9 +226,16 @@
}
#endif
- status_t result = (*functor)();
+ float bounds[4];
+ status_t result = (*functor)(&bounds[0], 4);
+
+ if (result != 0) {
+ Rect localDirty(bounds[0], bounds[1], bounds[2], bounds[3]);
+ dirty.unionWith(localDirty);
+ }
+
resume();
- return (result == 0) ? false : true;
+ return result != 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -1057,11 +1064,11 @@
// Drawing
///////////////////////////////////////////////////////////////////////////////
-bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList) {
- return displayList->replay(*this, level);
+ return displayList->replay(*this, dirty, level);
}
return false;
}
@@ -1522,7 +1529,6 @@
break;
}
- // TODO: Handle paint->getTextScaleX()
const float oldX = x;
const float oldY = y;
const bool pureTranslate = mSnapshot->transform->isPureTranslate();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7bbf034..9d86388 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -70,7 +70,7 @@
virtual void interrupt();
virtual void resume();
- virtual bool callDrawGLFunction(Functor *functor);
+ virtual bool callDrawGLFunction(Functor *functor, Rect& dirty);
int getSaveCount() const;
virtual int save(int flags);
@@ -96,7 +96,7 @@
bool quickReject(float left, float top, float right, float bottom);
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- virtual bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+ virtual bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 62c4250..d46686d 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -42,6 +42,17 @@
textSize = paint->getTextSize();
typeface = paint->getTypeface();
+
+ flags = 0;
+ if (paint->isFakeBoldText()) {
+ flags |= Font::kFakeBold;
+ }
+
+ const float skewX = paint->getTextSkewX();
+ italicStyle = *(uint32_t*) &skewX;
+
+ const float scaleXFloat = paint->getTextScaleX();
+ scaleX = *(uint32_t*) &scaleXFloat;
}
~ShadowText() {
@@ -51,6 +62,9 @@
uint32_t len;
float textSize;
SkTypeface* typeface;
+ uint32_t flags;
+ uint32_t italicStyle;
+ uint32_t scaleX;
const char16_t* text;
String16 str;
@@ -65,7 +79,13 @@
LTE_INT(radius) {
LTE_FLOAT(textSize) {
LTE_INT(typeface) {
- return strncmp16(text, rhs.text, len >> 1) < 0;
+ LTE_INT(flags) {
+ LTE_INT(italicStyle) {
+ LTE_INT(scaleX) {
+ return strncmp16(text, rhs.text, len >> 1) < 0;
+ }
+ }
+ }
}
}
}
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
index b2f547b..7069b23 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -140,7 +140,7 @@
try {
properties = mMANativeHelper.getMediaProperties(filename);
} catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found");
+ throw new IllegalArgumentException(e.getMessage() + " : " + filename);
}
switch (mMANativeHelper.getFileType(properties.fileType)) {
case MediaProperties.FILE_3GP:
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index c91d796..4758de6 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -115,7 +115,7 @@
try {
properties = mMANativeHelper.getMediaProperties(filename);
} catch ( Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found: " + filename);
+ throw new IllegalArgumentException(e.getMessage() + " : " + filename);
}
switch (mMANativeHelper.getFileType(properties.fileType)) {
diff --git a/media/java/android/mtp/MtpClient.java b/media/java/android/mtp/MtpClient.java
index 40e2f9b..d25dcb9 100644
--- a/media/java/android/mtp/MtpClient.java
+++ b/media/java/android/mtp/MtpClient.java
@@ -16,6 +16,7 @@
package android.mtp;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -41,6 +42,9 @@
private static final String TAG = "MtpClient";
+ private static final String ACTION_USB_PERMISSION =
+ "android.mtp.MtpClient.action.USB_PERMISSION";
+
private final Context mContext;
private final UsbManager mUsbManager;
private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
@@ -49,29 +53,47 @@
// mDevices is also used for synchronization in this class.
private final HashMap<String, MtpDevice> mDevices = new HashMap<String, MtpDevice>();
+ private final PendingIntent mPermissionIntent;
+
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
UsbDevice usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
String deviceName = usbDevice.getDeviceName();
synchronized (mDevices) {
MtpDevice mtpDevice = mDevices.get(deviceName);
- if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
+ if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
if (mtpDevice == null) {
mtpDevice = openDeviceLocked(usbDevice);
}
if (mtpDevice != null) {
- mDevices.put(deviceName, mtpDevice);
for (Listener listener : mListeners) {
listener.deviceAdded(mtpDevice);
}
}
- } else if (mtpDevice != null) {
- mDevices.remove(deviceName);
- for (Listener listener : mListeners) {
- listener.deviceRemoved(mtpDevice);
+ } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
+ if (mtpDevice != null) {
+ mDevices.remove(deviceName);
+ for (Listener listener : mListeners) {
+ listener.deviceRemoved(mtpDevice);
+ }
+ }
+ } else if (ACTION_USB_PERMISSION.equals(action)) {
+ boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED,
+ false);
+ Log.d(TAG, "ACTION_USB_PERMISSION: " + permission);
+ if (permission) {
+ if (mtpDevice == null) {
+ mtpDevice = openDeviceLocked(usbDevice);
+ }
+ if (mtpDevice != null) {
+ for (Listener listener : mListeners) {
+ listener.deviceAdded(mtpDevice);
+ }
+ }
}
}
}
@@ -126,10 +148,11 @@
public MtpClient(Context context) {
mContext = context;
mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
-
+ mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
+ filter.addAction(ACTION_USB_PERMISSION);
context.registerReceiver(mUsbReceiver, filter);
}
@@ -142,9 +165,14 @@
*/
private MtpDevice openDeviceLocked(UsbDevice usbDevice) {
if (isCamera(usbDevice)) {
- MtpDevice mtpDevice = new MtpDevice(usbDevice);
- if (mtpDevice.open(mUsbManager)) {
- return mtpDevice;
+ if (!mUsbManager.hasPermission(usbDevice)) {
+ mUsbManager.requestPermission(usbDevice, mPermissionIntent);
+ } else {
+ MtpDevice mtpDevice = new MtpDevice(usbDevice);
+ if (mtpDevice.open(mUsbManager)) {
+ mDevices.put(usbDevice.getDeviceName(), mtpDevice);
+ return mtpDevice;
+ }
}
}
return null;
@@ -218,13 +246,8 @@
// Query the USB manager since devices might have attached
// before we added our listener.
for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
- String deviceName = usbDevice.getDeviceName();
- MtpDevice mtpDevice = mDevices.get(deviceName);
- if (mtpDevice == null) {
- mtpDevice = openDeviceLocked(usbDevice);
- }
- if (mtpDevice != null) {
- mDevices.put(deviceName, mtpDevice);
+ if (mDevices.get(usbDevice.getDeviceName()) == null) {
+ openDeviceLocked(usbDevice);
}
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 98de2f7..b4a4689 100644
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -20,6 +20,7 @@
import android.content.ContentValues;
import android.content.IContentProvider;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.MediaScanner;
@@ -62,8 +63,8 @@
// true if the database has been modified in the current MTP session
private boolean mDatabaseModified;
- // database for writable MTP device properties
- private SQLiteDatabase mDevicePropDb;
+ // SharedPreferences for writable MTP device properties
+ private SharedPreferences mDeviceProperties;
private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
// FIXME - this should be passed in via the constructor
@@ -96,9 +97,6 @@
private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
+ Files.FileColumns.FORMAT + "=?";
- private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" };
- private static final String DEVICE_PROPERTY_WHERE = "code=?";
-
private final MediaScanner mMediaScanner;
static {
@@ -114,7 +112,7 @@
mMediaStoragePath = storagePath;
mObjectsUri = Files.getMtpObjectsUri(volumeName);
mMediaScanner = new MediaScanner(context);
- openDevicePropertiesDatabase(context);
+ initDeviceProperties(context);
}
@Override
@@ -126,19 +124,38 @@
}
}
- private void openDevicePropertiesDatabase(Context context) {
- mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
- int version = mDevicePropDb.getVersion();
+ private void initDeviceProperties(Context context) {
+ final String devicePropertiesName = "device-properties";
+ mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE);
+ File databaseFile = context.getDatabasePath(devicePropertiesName);
- // initialize if necessary
- if (version != DEVICE_PROPERTIES_DATABASE_VERSION) {
- mDevicePropDb.execSQL("CREATE TABLE properties (" +
- "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
- "code INTEGER UNIQUE ON CONFLICT REPLACE," +
- "value TEXT" +
- ");");
- mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);");
- mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION);
+ if (databaseFile.exists()) {
+ // for backward compatibility - read device properties from sqlite database
+ // and migrate them to shared prefs
+ SQLiteDatabase db = null;
+ Cursor c = null;
+ try {
+ db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
+ if (db != null) {
+ c = db.query("properties", new String[] { "_id", "code", "value" },
+ null, null, null, null, null);
+ if (c != null) {
+ SharedPreferences.Editor e = mDeviceProperties.edit();
+ while (c.moveToNext()) {
+ String name = c.getString(1);
+ String value = c.getString(2);
+ e.putString(name, value);
+ }
+ e.commit();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "failed to migrate device properties", e);
+ } finally {
+ if (c != null) c.close();
+ if (db != null) db.close();
+ }
+ databaseFile.delete();
}
}
@@ -567,30 +584,15 @@
switch (property) {
case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
- // writable string properties kept in our device property database
- Cursor c = null;
- try {
- c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION,
- DEVICE_PROPERTY_WHERE, new String[] { Integer.toString(property) },
- null, null, null);
-
- if (c != null && c.moveToNext()) {
- String value = c.getString(1);
- int length = value.length();
- if (length > 255) {
- length = 255;
- }
- value.getChars(0, length, outStringValue, 0);
- outStringValue[length] = 0;
- } else {
- outStringValue[0] = 0;
- }
- return MtpConstants.RESPONSE_OK;
- } finally {
- if (c != null) {
- c.close();
- }
+ // writable string properties kept in shared preferences
+ String value = mDeviceProperties.getString(Integer.toString(property), "");
+ int length = value.length();
+ if (length > 255) {
+ length = 255;
}
+ value.getChars(0, length, outStringValue, 0);
+ outStringValue[length] = 0;
+ return MtpConstants.RESPONSE_OK;
case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
// use screen size as max image size
@@ -612,16 +614,11 @@
switch (property) {
case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
- // writable string properties kept in our device property database
- try {
- ContentValues values = new ContentValues();
- values.put("code", property);
- values.put("value", stringValue);
- mDevicePropDb.insert("properties", "code", values);
- return MtpConstants.RESPONSE_OK;
- } catch (Exception e) {
- return MtpConstants.RESPONSE_GENERAL_ERROR;
- }
+ // writable string properties kept in shared prefs
+ SharedPreferences.Editor e = mDeviceProperties.edit();
+ e.putString(Integer.toString(property), stringValue);
+ return (e.commit() ? MtpConstants.RESPONSE_OK
+ : MtpConstants.RESPONSE_GENERAL_ERROR);
}
return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
index 423e93f..035f59a 100755
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ b/media/jni/mediaeditor/VideoEditorOsal.cpp
@@ -207,6 +207,7 @@
VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIOBITRATE_TOO_HIGH ),
VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL ),
VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_NOMORE_SPACE ),
+ VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_FILE_DRM_PROTECTED ),
// M4READER_Common.h
VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_READER_UNKNOWN_STREAM_TYPE ),
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
index 73a7c9c..3b795ce 100755
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
@@ -204,10 +204,17 @@
result = getClipProperties(
pEnv, thiz, pFile, clipType, pClipProperties);
- // Check if the creation succeeded.
- videoEditJava_checkAndThrowIllegalArgumentException(
- &gotten, pEnv,(M4NO_ERROR != result),
- "Invalid File or File not found");
+ if (M4MCS_ERR_FILE_DRM_PROTECTED == result) {
+ // Check if the creation succeeded.
+ videoEditJava_checkAndThrowIllegalArgumentException(
+ &gotten, pEnv,(M4NO_ERROR != result),
+ "Invalid File - DRM Protected ");
+ } else {
+ // Check if the creation succeeded.
+ videoEditJava_checkAndThrowIllegalArgumentException(
+ &gotten, pEnv,(M4NO_ERROR != result),
+ "Invalid File or File not found ");
+ }
/**
* Max resolution supported is 1280 x 720.
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d3d1750..fee245f 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -8,6 +8,7 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.GET_TASKS" />
+ <uses-permission android:name="android.permission.MANAGE_USB" />
<application
android:persistent="true"
@@ -39,5 +40,22 @@
android:exported="true">
</activity>
+ <!-- started from UsbDeviceSettingsManager -->
+ <activity android:name=".usb.UsbPermissionActivity"
+ android:exported="true"
+ android:permission="android.permission.MANAGE_USB"
+ android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true">
+ </activity>
+
+ <!-- started from UsbDeviceSettingsManager -->
+ <activity android:name=".usb.UsbResolverActivity"
+ android:exported="true"
+ android:permission="android.permission.MANAGE_USB"
+ android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true">
+ </activity>
</application>
</manifest>
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml
index bfa6c36..3f172e6 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml
@@ -38,8 +38,8 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
- android:layout_marginLeft="123dip"
- android:layout_marginTop="16dip"
+ android:layout_marginLeft="131dip"
+ android:layout_marginTop="13dip"
android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width"
android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height"
android:adjustViewBounds="true"
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml
index eda19b7..42940be 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml
@@ -51,7 +51,7 @@
android:stackFromBottom="true"
android:fadingEdge="vertical"
android:scrollbars="none"
- android:fadingEdgeLength="30dip"
+ android:fadingEdgeLength="20dip"
android:listSelector="@drawable/recents_thumbnail_bg_selector"
/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ebd48e7..becad6a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -115,4 +115,11 @@
<!-- Label of a toggle switch to disable use of the physical keyboard in favor of the IME. [CHAR LIMIT=25] -->
<string name="status_bar_use_physical_keyboard">Use physical keyboard</string>
+
+ <!-- Prompt for the USB device permission dialog [CHAR LIMIT=80] -->
+ <string name="usb_device_permission_prompt">Allow the application %1$s to access the USB device?</string>
+
+ <!-- Prompt for the USB accessory permission dialog [CHAR LIMIT=80] -->
+ <string name="usb_accessory_permission_prompt">Allow the application %1$s to access the USB accessory?</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java
new file mode 100644
index 0000000..1edebbb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java
@@ -0,0 +1,67 @@
+/*
+ * 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.systemui.usb;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+
+// This class is used to close UsbPermissionsActivity and UsbResolverActivity
+// if their device/accessory is disconnected while the dialog is still open
+class UsbDisconnectedReceiver extends BroadcastReceiver {
+ private final Activity mActivity;
+ private UsbDevice mDevice;
+ private UsbAccessory mAccessory;
+
+ public UsbDisconnectedReceiver(Activity activity, UsbDevice device) {
+ mActivity = activity;
+ mDevice = device;
+
+ IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
+ activity.registerReceiver(this, filter);
+ }
+
+ public UsbDisconnectedReceiver(Activity activity, UsbAccessory accessory) {
+ mActivity = activity;
+ mAccessory = accessory;
+
+ IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
+ activity.registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
+ UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ if (device != null && device.equals(mDevice)) {
+ mActivity.finish();
+ }
+ } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
+ UsbAccessory accessory =
+ (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
+ if (accessory != null && accessory.equals(mAccessory)) {
+ mActivity.finish();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
new file mode 100644
index 0000000..f1784df
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 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.systemui.usb;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.hardware.usb.IUsbManager;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.TextView;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+
+import com.android.systemui.R;
+
+public class UsbPermissionActivity extends AlertActivity
+ implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
+
+ private static final String TAG = "UsbPermissionActivity";
+
+ private CheckBox mAlwaysCheck;
+ private TextView mClearDefaultHint;
+ private UsbDevice mDevice;
+ private UsbAccessory mAccessory;
+ private PendingIntent mPendingIntent;
+ private String mPackageName;
+ private int mUid;
+ private boolean mPermissionGranted;
+ private UsbDisconnectedReceiver mDisconnectedReceiver;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ Intent intent = getIntent();
+ mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
+ mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT);
+ mUid = intent.getIntExtra("uid", 0);
+ mPackageName = intent.getStringExtra("package");
+
+ PackageManager packageManager = getPackageManager();
+ ApplicationInfo aInfo;
+ try {
+ aInfo = packageManager.getApplicationInfo(mPackageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "unable to look up package name", e);
+ finish();
+ return;
+ }
+ String appName = aInfo.loadLabel(packageManager).toString();
+
+ final AlertController.AlertParams ap = mAlertParams;
+ ap.mIcon = aInfo.loadIcon(packageManager);
+ ap.mTitle = appName;
+ if (mDevice == null) {
+ ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName);
+ mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
+ } else {
+ ap.mMessage = getString(R.string.usb_device_permission_prompt, appName);
+ mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
+ }
+ ap.mPositiveButtonText = getString(com.android.internal.R.string.ok);
+ ap.mNegativeButtonText = getString(com.android.internal.R.string.cancel);
+ ap.mPositiveButtonListener = this;
+ ap.mNegativeButtonListener = this;
+
+ // add "always use" checkbox
+ LayoutInflater inflater = (LayoutInflater)getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
+ mAlwaysCheck = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
+ mAlwaysCheck.setText(com.android.internal.R.string.alwaysUse);
+ mAlwaysCheck.setOnCheckedChangeListener(this);
+ mClearDefaultHint = (TextView)ap.mView.findViewById(
+ com.android.internal.R.id.clearDefaultHint);
+ mClearDefaultHint.setVisibility(View.GONE);
+
+ setupAlert();
+
+ }
+
+ @Override
+ public void onDestroy() {
+ IBinder b = ServiceManager.getService(USB_SERVICE);
+ IUsbManager service = IUsbManager.Stub.asInterface(b);
+
+ // send response via pending intent
+ Intent intent = new Intent();
+ try {
+ if (mDevice != null) {
+ intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice);
+ if (mPermissionGranted) {
+ service.grantDevicePermission(mDevice, mUid);
+ if (mAlwaysCheck.isChecked()) {
+ service.setDevicePackage(mDevice, mPackageName);
+ }
+ }
+ }
+ if (mAccessory != null) {
+ intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory);
+ if (mPermissionGranted) {
+ service.grantAccessoryPermission(mAccessory, mUid);
+ if (mAlwaysCheck.isChecked()) {
+ service.setAccessoryPackage(mAccessory, mPackageName);
+ }
+ }
+ }
+ intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, mPermissionGranted);
+ mPendingIntent.send(this, 0, intent);
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "PendingIntent was cancelled");
+ } catch (RemoteException e) {
+ Log.e(TAG, "IUsbService connection failed", e);
+ }
+
+ if (mDisconnectedReceiver != null) {
+ unregisterReceiver(mDisconnectedReceiver);
+ }
+ super.onDestroy();
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == AlertDialog.BUTTON_POSITIVE) {
+ mPermissionGranted = true;
+ }
+ finish();
+ }
+
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (mClearDefaultHint == null) return;
+
+ if(isChecked) {
+ mClearDefaultHint.setVisibility(View.VISIBLE);
+ } else {
+ mClearDefaultHint.setVisibility(View.GONE);
+ }
+ }
+}
diff --git a/services/java/com/android/server/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
similarity index 70%
rename from services/java/com/android/server/usb/UsbResolverActivity.java
rename to packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index e8a09a5..84d73dd 100644
--- a/services/java/com/android/server/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.usb;
+package com.android.systemui.usb;
import com.android.internal.app.ResolverActivity;
@@ -39,6 +39,10 @@
public static final String TAG = "UsbResolverActivity";
public static final String EXTRA_RESOLVE_INFOS = "rlist";
+ private UsbDevice mDevice;
+ private UsbAccessory mAccessory;
+ private UsbDisconnectedReceiver mDisconnectedReceiver;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
@@ -50,7 +54,6 @@
}
Intent target = (Intent)targetParcelable;
ArrayList<ResolveInfo> rList = intent.getParcelableArrayListExtra(EXTRA_RESOLVE_INFOS);
- Log.d(TAG, "rList.size() " + rList.size());
CharSequence title = getResources().getText(com.android.internal.R.string.chooseUsbActivity);
super.onCreate(savedInstanceState, target, title, null, rList,
true, /* Set alwaysUseOption to true to enable "always use this app" checkbox. */
@@ -58,6 +61,27 @@
This is necessary because this activity is needed for the user to allow
the application permission to access the device */
);
+
+ mDevice = (UsbDevice)target.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ if (mDevice != null) {
+ mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
+ } else {
+ mAccessory = (UsbAccessory)target.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
+ if (mAccessory == null) {
+ Log.e(TAG, "no device or accessory");
+ finish();
+ return;
+ }
+ mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mDisconnectedReceiver != null) {
+ unregisterReceiver(mDisconnectedReceiver);
+ }
+ super.onDestroy();
}
protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) {
@@ -65,28 +89,24 @@
IBinder b = ServiceManager.getService(USB_SERVICE);
IUsbManager service = IUsbManager.Stub.asInterface(b);
int uid = ri.activityInfo.applicationInfo.uid;
- String action = intent.getAction();
- if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
- UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ if (mDevice != null) {
// grant permission for the device
- service.grantDevicePermission(device, uid);
+ service.grantDevicePermission(mDevice, uid);
// set or clear default setting
if (alwaysCheck) {
- service.setDevicePackage(device, ri.activityInfo.packageName);
+ service.setDevicePackage(mDevice, ri.activityInfo.packageName);
} else {
- service.setDevicePackage(device, null);
+ service.setDevicePackage(mDevice, null);
}
- } else if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
- UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(
- UsbManager.EXTRA_ACCESSORY);
+ } else if (mAccessory != null) {
// grant permission for the accessory
- service.grantAccessoryPermission(accessory, uid);
+ service.grantAccessoryPermission(mAccessory, uid);
// set or clear default setting
if (alwaysCheck) {
- service.setAccessoryPackage(accessory, ri.activityInfo.packageName);
+ service.setAccessoryPackage(mAccessory, ri.activityInfo.packageName);
} else {
- service.setAccessoryPackage(accessory, null);
+ service.setAccessoryPackage(mAccessory, null);
}
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index adc49ae..3c6c427 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -62,6 +62,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicBoolean;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -99,9 +100,6 @@
/* Chipset supports background scan */
private final boolean mBackgroundScanSupported;
- // true if the user enabled Wifi while in airplane mode
- private AtomicBoolean mAirplaneModeOverwridden = new AtomicBoolean(false);
-
private final LockList mLocks = new LockList();
// some wifi lock statistics
private int mFullHighPerfLocksAcquired;
@@ -144,6 +142,14 @@
private static final String ACTION_DEVICE_IDLE =
"com.android.server.WifiManager.action.DEVICE_IDLE";
+ private static final int WIFI_DISABLED = 0;
+ private static final int WIFI_ENABLED = 1;
+ /* Wifi enabled while in airplane mode */
+ private static final int WIFI_ENABLED_AIRPLANE_OVERRIDE = 2;
+
+ private AtomicInteger mWifiState = new AtomicInteger(WIFI_DISABLED);
+ private AtomicBoolean mAirplaneModeOn = new AtomicBoolean(false);
+
private boolean mIsReceiverRegistered = false;
@@ -338,11 +344,11 @@
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- // clear our flag indicating the user has overwridden airplane mode
- mAirplaneModeOverwridden.set(false);
- // on airplane disable, restore Wifi if the saved state indicates so
- if (!isAirplaneModeOn() && testAndClearWifiSavedState()) {
- persistWifiEnabled(true);
+ mAirplaneModeOn.set(isAirplaneModeOn());
+ /* On airplane mode disable, restore wifi state if necessary */
+ if (!mAirplaneModeOn.get() && (testAndClearWifiSavedState() ||
+ mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE)) {
+ persistWifiEnabled(true);
}
updateWifiState();
}
@@ -402,9 +408,10 @@
* This function is used only at boot time
*/
public void checkAndStartWifi() {
- /* Start if Wi-Fi is enabled or the saved state indicates Wi-Fi was on */
- boolean wifiEnabled = !isAirplaneModeOn()
- && (getPersistedWifiEnabled() || testAndClearWifiSavedState());
+ mAirplaneModeOn.set(isAirplaneModeOn());
+ mWifiState.set(getPersistedWifiState());
+ /* Start if Wi-Fi should be enabled or the saved state indicates Wi-Fi was on */
+ boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState();
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
(wifiEnabled ? "enabled" : "disabled"));
setWifiEnabled(wifiEnabled);
@@ -423,21 +430,39 @@
return (wifiSavedState == 1);
}
- private boolean getPersistedWifiEnabled() {
+ private int getPersistedWifiState() {
final ContentResolver cr = mContext.getContentResolver();
try {
- return Settings.Secure.getInt(cr, Settings.Secure.WIFI_ON) == 1;
+ return Settings.Secure.getInt(cr, Settings.Secure.WIFI_ON);
} catch (Settings.SettingNotFoundException e) {
- Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, 0);
- return false;
+ Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, WIFI_DISABLED);
+ return WIFI_DISABLED;
+ }
+ }
+
+ private boolean shouldWifiBeEnabled() {
+ if (mAirplaneModeOn.get()) {
+ return mWifiState.get() == WIFI_ENABLED_AIRPLANE_OVERRIDE;
+ } else {
+ return mWifiState.get() != WIFI_DISABLED;
}
}
private void persistWifiEnabled(boolean enabled) {
final ContentResolver cr = mContext.getContentResolver();
- Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, enabled ? 1 : 0);
+ if (enabled) {
+ if (isAirplaneModeOn() && isAirplaneToggleable()) {
+ mWifiState.set(WIFI_ENABLED_AIRPLANE_OVERRIDE);
+ } else {
+ mWifiState.set(WIFI_ENABLED);
+ }
+ } else {
+ mWifiState.set(WIFI_DISABLED);
+ }
+ Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, mWifiState.get());
}
+
/**
* see {@link android.net.wifi.WifiManager#pingSupplicant()}
* @return {@code true} if the operation succeeds, {@code false} otherwise
@@ -490,11 +515,6 @@
Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
}
- // set a flag if the user is enabling Wifi while in airplane mode
- if (enable && isAirplaneModeOn() && isAirplaneToggleable()) {
- mAirplaneModeOverwridden.set(true);
- }
-
if (enable) {
reportStartWorkSource();
}
@@ -1037,11 +1057,8 @@
}
private void updateWifiState() {
- boolean wifiEnabled = getPersistedWifiEnabled();
- boolean airplaneMode = isAirplaneModeOn() && !mAirplaneModeOverwridden.get();
boolean lockHeld = mLocks.hasLocks();
int strongestLockMode = WifiManager.WIFI_MODE_FULL;
- boolean wifiShouldBeEnabled = wifiEnabled && !airplaneMode;
boolean wifiShouldBeStarted = !mDeviceIdle || lockHeld;
if (lockHeld) {
@@ -1053,11 +1070,11 @@
}
/* Disable tethering when airplane mode is enabled */
- if (airplaneMode) {
+ if (mAirplaneModeOn.get()) {
mWifiStateMachine.setWifiApEnabled(null, false);
}
- if (wifiShouldBeEnabled) {
+ if (shouldWifiBeEnabled()) {
if (wifiShouldBeStarted) {
reportStartWorkSource();
mWifiStateMachine.setWifiEnabled(true);
diff --git a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java
index 2f22fe1..29e6f94 100644
--- a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java
@@ -16,11 +16,13 @@
package com.android.server.usb;
+import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
@@ -602,50 +604,20 @@
}
public void deviceAttached(UsbDevice device) {
- Intent deviceIntent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
- deviceIntent.putExtra(UsbManager.EXTRA_DEVICE, device);
- deviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
+ intent.putExtra(UsbManager.EXTRA_DEVICE, device);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ArrayList<ResolveInfo> matches;
String defaultPackage;
synchronized (mLock) {
- matches = getDeviceMatchesLocked(device, deviceIntent);
+ matches = getDeviceMatchesLocked(device, intent);
// Launch our default activity directly, if we have one.
// Otherwise we will start the UsbResolverActivity to allow the user to choose.
defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device));
}
- int count = matches.size();
- // don't show the resolver activity if there are no choices available
- if (count == 0) return;
-
- if (defaultPackage != null) {
- for (int i = 0; i < count; i++) {
- ResolveInfo rInfo = matches.get(i);
- if (rInfo.activityInfo != null &&
- defaultPackage.equals(rInfo.activityInfo.packageName)) {
- try {
- deviceIntent.setComponent(new ComponentName(
- defaultPackage, rInfo.activityInfo.name));
- mContext.startActivity(deviceIntent);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "startActivity failed", e);
- }
- return;
- }
- }
- }
-
- Intent intent = new Intent(mContext, UsbResolverActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- intent.putExtra(Intent.EXTRA_INTENT, deviceIntent);
- intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, matches);
- try {
- mContext.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "unable to start UsbResolverActivity");
- }
+ resolveActivity(intent, matches, defaultPackage, device, null);
}
public void deviceDetached(UsbDevice device) {
@@ -656,49 +628,86 @@
}
public void accessoryAttached(UsbAccessory accessory) {
- Intent accessoryIntent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
- accessoryIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
- accessoryIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
+ intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ArrayList<ResolveInfo> matches;
String defaultPackage;
synchronized (mLock) {
- matches = getAccessoryMatchesLocked(accessory, accessoryIntent);
+ matches = getAccessoryMatchesLocked(accessory, intent);
// Launch our default activity directly, if we have one.
// Otherwise we will start the UsbResolverActivity to allow the user to choose.
defaultPackage = mAccessoryPreferenceMap.get(new AccessoryFilter(accessory));
}
+ resolveActivity(intent, matches, defaultPackage, null, accessory);
+ }
+
+ private void resolveActivity(Intent intent, ArrayList<ResolveInfo> matches,
+ String defaultPackage, UsbDevice device, UsbAccessory accessory) {
int count = matches.size();
// don't show the resolver activity if there are no choices available
if (count == 0) return;
- if (defaultPackage != null) {
- for (int i = 0; i < count; i++) {
- ResolveInfo rInfo = matches.get(i);
- if (rInfo.activityInfo != null &&
- defaultPackage.equals(rInfo.activityInfo.packageName)) {
- try {
- accessoryIntent.setComponent(new ComponentName(
- defaultPackage, rInfo.activityInfo.name));
- mContext.startActivity(accessoryIntent);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "startActivity failed", e);
- }
- return;
+ ResolveInfo defaultRI = null;
+ if (count == 1 && defaultPackage == null) {
+ // Check to see if our single choice is on the system partition.
+ // If so, treat it as our default without calling UsbResolverActivity
+ ResolveInfo rInfo = matches.get(0);
+ if (rInfo.activityInfo != null &&
+ rInfo.activityInfo.applicationInfo != null &&
+ (rInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ defaultRI = rInfo;
+ int uid = rInfo.activityInfo.applicationInfo.uid;
+ // grant permission
+ if (device != null) {
+ grantDevicePermission(device, uid);
+ } else if (accessory != null) {
+ grantAccessoryPermission(accessory, uid);
}
}
}
- Intent intent = new Intent(mContext, UsbResolverActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (defaultRI == null && defaultPackage != null) {
+ // look for default activity
+ for (int i = 0; i < count; i++) {
+ ResolveInfo rInfo = matches.get(i);
+ if (rInfo.activityInfo != null &&
+ defaultPackage.equals(rInfo.activityInfo.packageName)) {
+ defaultRI = rInfo;
+ break;
+ }
+ }
+ }
- intent.putExtra(Intent.EXTRA_INTENT, accessoryIntent);
- intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, matches);
- try {
- mContext.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "unable to start UsbResolverActivity");
+ if (defaultRI != null) {
+ // start default activity directly
+ try {
+ intent.setComponent(
+ new ComponentName(defaultRI.activityInfo.packageName,
+ defaultRI.activityInfo.name));
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "startActivity failed", e);
+ }
+ } else {
+ long identity = Binder.clearCallingIdentity();
+
+ // start UsbResolverActivity so user can choose an activity
+ Intent resolverIntent = new Intent();
+ resolverIntent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbResolverActivity");
+ resolverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ resolverIntent.putExtra(Intent.EXTRA_INTENT, intent);
+ resolverIntent.putParcelableArrayListExtra("rlist", matches);
+ try {
+ mContext.startActivity(resolverIntent);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "unable to start UsbResolverActivity");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
@@ -709,40 +718,121 @@
mContext.sendBroadcast(intent);
}
- public void checkPermission(UsbDevice device) {
- if (device == null) return;
+ public boolean hasPermission(UsbDevice device) {
synchronized (mLock) {
- ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(Binder.getCallingUid());
+ ArrayList<DeviceFilter> filterList =
+ mDevicePermissionMap.get(Binder.getCallingUid());
if (filterList != null) {
int count = filterList.size();
for (int i = 0; i < count; i++) {
DeviceFilter filter = filterList.get(i);
if (filter.equals(device)) {
// permission allowed
- return;
+ return true;
}
}
}
}
- throw new SecurityException("User has not given permission to device " + device);
+ return false;
}
- public void checkPermission(UsbAccessory accessory) {
- if (accessory == null) return;
+ public boolean hasPermission(UsbAccessory accessory) {
synchronized (mLock) {
- ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(Binder.getCallingUid());
+ ArrayList<AccessoryFilter> filterList =
+ mAccessoryPermissionMap.get(Binder.getCallingUid());
if (filterList != null) {
int count = filterList.size();
for (int i = 0; i < count; i++) {
AccessoryFilter filter = filterList.get(i);
if (filter.equals(accessory)) {
// permission allowed
- return;
+ return true;
}
}
}
}
- throw new SecurityException("User has not given permission to accessory " + accessory);
+ return false;
+ }
+
+ public void checkPermission(UsbDevice device) {
+ if (!hasPermission(device)) {
+ throw new SecurityException("User has not given permission to device " + device);
+ }
+ }
+
+ public void checkPermission(UsbAccessory accessory) {
+ if (!hasPermission(accessory)) {
+ throw new SecurityException("User has not given permission to accessory " + accessory);
+ }
+ }
+
+ private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) {
+ int uid = Binder.getCallingUid();
+
+ // compare uid with packageName to foil apps pretending to be someone else
+ try {
+ ApplicationInfo aInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0);
+ if (aInfo.uid != uid) {
+ throw new IllegalArgumentException("package " + packageName +
+ " does not match caller's uid " + uid);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalArgumentException("package " + packageName + " not found");
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbPermissionActivity");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(Intent.EXTRA_INTENT, pi);
+ intent.putExtra("package", packageName);
+ intent.putExtra("uid", uid);
+ try {
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "unable to start UsbPermissionActivity");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ public void requestPermission(UsbDevice device, String packageName, PendingIntent pi) {
+ Intent intent = new Intent();
+
+ // respond immediately if permission has already been granted
+ if (hasPermission(device)) {
+ intent.putExtra(UsbManager.EXTRA_DEVICE, device);
+ intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
+ try {
+ pi.send(mContext, 0, intent);
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "requestPermission PendingIntent was cancelled");
+ }
+ return;
+ }
+
+ // start UsbPermissionActivity so user can choose an activity
+ intent.putExtra(UsbManager.EXTRA_DEVICE, device);
+ requestPermissionDialog(intent, packageName, pi);
+ }
+
+ public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) {
+ Intent intent = new Intent();
+
+ // respond immediately if permission has already been granted
+ if (hasPermission(accessory)) {
+ intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+ intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
+ try {
+ pi.send(mContext, 0, intent);
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "requestPermission PendingIntent was cancelled");
+ }
+ return;
+ }
+
+ intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+ requestPermissionDialog(intent, packageName, pi);
}
public void setDevicePackage(UsbDevice device, String packageName) {
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 8170c61..d0a2492 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -16,6 +16,7 @@
package com.android.server.usb;
+import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -454,6 +455,24 @@
mDeviceManager.setAccessoryPackage(accessory, packageName);
}
+ public boolean hasDevicePermission(UsbDevice device) {
+ return mDeviceManager.hasPermission(device);
+ }
+
+ public boolean hasAccessoryPermission(UsbAccessory accessory) {
+ return mDeviceManager.hasPermission(accessory);
+ }
+
+ public void requestDevicePermission(UsbDevice device, String packageName,
+ PendingIntent pi) {
+ mDeviceManager.requestPermission(device, packageName, pi);
+ }
+
+ public void requestAccessoryPermission(UsbAccessory accessory, String packageName,
+ PendingIntent pi) {
+ mDeviceManager.requestPermission(accessory, packageName, pi);
+ }
+
public void grantDevicePermission(UsbDevice device, int uid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.grantDevicePermission(device, uid);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index eed41a0..8ccfbba 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -4791,13 +4791,17 @@
if (maxLayer < ws.mAnimLayer) {
maxLayer = ws.mAnimLayer;
}
- final Rect wf = ws.mFrame;
- final Rect cr = ws.mContentInsets;
- int left = wf.left + cr.left;
- int top = wf.top + cr.top;
- int right = wf.right - cr.right;
- int bottom = wf.bottom - cr.bottom;
- frame.union(left, top, right, bottom);
+
+ // Don't include wallpaper in bounds calculation
+ if (!ws.mIsWallpaper) {
+ final Rect wf = ws.mFrame;
+ final Rect cr = ws.mContentInsets;
+ int left = wf.left + cr.left;
+ int top = wf.top + cr.top;
+ int right = wf.right - cr.right;
+ int bottom = wf.bottom - cr.bottom;
+ frame.union(left, top, right, bottom);
+ }
}
Binder.restoreCallingIdentity(ident);
@@ -5460,8 +5464,9 @@
shortSize = (int)(shortSize/dm.density);
// These semi-magic numbers define our compatibility modes for
- // applications with different screens. Don't change unless you
- // make sure to test lots and lots of apps!
+ // applications with different screens. These are guarantees to
+ // app developers about the space they can expect for a particular
+ // configuration. DO NOT CHANGE!
if (longSize < 470) {
// This is shorter than an HVGA normal density screen (which
// is 480 pixels on its long side).
@@ -5469,12 +5474,12 @@
| Configuration.SCREENLAYOUT_LONG_NO;
} else {
// What size is this screen screen?
- if (longSize >= 800 && shortSize >= 600) {
- // SVGA or larger screens at medium density are the point
+ if (longSize >= 960 && shortSize >= 720) {
+ // 1.5xVGA or larger screens at medium density are the point
// at which we consider it to be an extra large screen.
mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
- } else if (longSize >= 530 && shortSize >= 400) {
- // SVGA or larger screens at high density are the point
+ } else if (longSize >= 640 && shortSize >= 480) {
+ // VGA or larger screens at medium density are the point
// at which we consider it to be a large screen.
mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
} else {
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 3be3b1b..bd4e787 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -727,14 +727,14 @@
};
if (wmActions & WM_ACTION_GO_TO_SLEEP) {
-#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+#if DEBUG_INPUT_DISPATCHER_POLICY
LOGD("handleInterceptActions: Going to sleep.");
#endif
android_server_PowerManagerService_goToSleep(when);
}
if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
-#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+#if DEBUG_INPUT_DISPATCHER_POLICY
LOGD("handleInterceptActions: Poking user activity.");
#endif
android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
@@ -743,7 +743,7 @@
if (wmActions & WM_ACTION_PASS_TO_USER) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
} else {
-#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+#if DEBUG_INPUT_DISPATCHER_POLICY
LOGD("handleInterceptActions: Not passing key to user.");
#endif
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
index e7f431c..3c8432e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
@@ -58,10 +58,12 @@
mScaledPaint = new Paint();
mScaledPaint.setAntiAlias(true);
mScaledPaint.setTextSize(16.0f);
+ mScaledPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff00ff00);
mSkewPaint = new Paint();
mSkewPaint.setAntiAlias(true);
- mSkewPaint.setTextSize(16.0f);
+ mSkewPaint.setTextSize(16.0f);
+ mSkewPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff000000);
}
@Override
@@ -106,11 +108,11 @@
mStrikePaint.setUnderlineText(true);
mSkewPaint.setTextSkewX(-0.25f);
- canvas.drawText("Hello OpenGL renderer!", 680, 200, mSkewPaint);
+ canvas.drawText("Hello OpenGL renderer!", 980, 200, mSkewPaint);
mSkewPaint.setTextSkewX(0.5f);
- canvas.drawText("Hello OpenGL renderer!", 680, 230, mSkewPaint);
+ canvas.drawText("Hello OpenGL renderer!", 980, 230, mSkewPaint);
mSkewPaint.setTextSkewX(0.0f);
- canvas.drawText("Hello OpenGL renderer!", 680, 260, mSkewPaint);
+ canvas.drawText("Hello OpenGL renderer!", 980, 260, mSkewPaint);
mScaledPaint.setTextScaleX(0.5f);
canvas.drawText("Hello OpenGL renderer!", 500, 200, mScaledPaint);
@@ -125,4 +127,4 @@
canvas.restore();
}
}
-}
\ No newline at end of file
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 6c9f48f..db14e53 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -28,10 +28,12 @@
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
/**
* Delegate implementing the native methods of android.graphics.Path
@@ -331,58 +333,91 @@
@LayoutlibDelegate
/*package*/ static void native_addOval(int nPath, RectF oval, int dir) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.addOval is not supported.", null, null /*data*/);
+ Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+ if (pathDelegate == null) {
+ return;
+ }
+
+ pathDelegate.mPath.append(new Ellipse2D.Float(
+ oval.left, oval.top, oval.width(), oval.height()), false);
}
@LayoutlibDelegate
/*package*/ static void native_addCircle(int nPath, float x, float y, float radius, int dir) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.addCircle is not supported.", null, null /*data*/);
+ Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+ if (pathDelegate == null) {
+ return;
+ }
+
+ // because x/y is the center of the circle, need to offset this by the radius
+ pathDelegate.mPath.append(new Ellipse2D.Float(
+ x - radius, y - radius, radius * 2, radius * 2), false);
}
@LayoutlibDelegate
/*package*/ static void native_addArc(int nPath, RectF oval,
float startAngle, float sweepAngle) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.addArc is not supported.", null, null /*data*/);
+ Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+ if (pathDelegate == null) {
+ return;
+ }
+
+ // because x/y is the center of the circle, need to offset this by the radius
+ pathDelegate.mPath.append(new Arc2D.Float(
+ oval.left, oval.top, oval.width(), oval.height(),
+ startAngle, sweepAngle, Arc2D.OPEN), false);
}
@LayoutlibDelegate
- /*package*/ static void native_addRoundRect(int nPath, RectF rect,
- float rx, float ry, int dir) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.addRoundRect is not supported.", null, null /*data*/);
+ /*package*/ static void native_addRoundRect(
+ int nPath, RectF rect, float rx, float ry, int dir) {
+
+ Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+ if (pathDelegate == null) {
+ return;
+ }
+
+ pathDelegate.mPath.append(new RoundRectangle2D.Float(
+ rect.left, rect.top, rect.width(), rect.height(), rx * 2, ry * 2), false);
}
@LayoutlibDelegate
- /*package*/ static void native_addRoundRect(int nPath, RectF r, float[] radii, int dir) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.addRoundRect is not supported.", null, null /*data*/);
+ /*package*/ static void native_addRoundRect(int nPath, RectF rect, float[] radii, int dir) {
+ // Java2D doesn't support different rounded corners in each corner, so just use the
+ // first value.
+ native_addRoundRect(nPath, rect, radii[0], radii[1], dir);
+
+ // there can be a case where this API is used but with similar values for all corners, so
+ // in that case we don't warn.
+ // we only care if 2 corners are different so just compare to the next one.
+ for (int i = 0 ; i < 3 ; i++) {
+ if (radii[i * 2] != radii[(i + 1) * 2] || radii[i * 2 + 1] != radii[(i + 1) * 2 + 1]) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "Different corner sizes are not supported in Path.addRoundRect.",
+ null, null /*data*/);
+ break;
+ }
+ }
}
@LayoutlibDelegate
/*package*/ static void native_addPath(int nPath, int src, float dx, float dy) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.addPath is not supported.", null, null /*data*/);
+ addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy));
}
@LayoutlibDelegate
/*package*/ static void native_addPath(int nPath, int src) {
- native_addPath(nPath, src, 0, 0);
+ addPath(nPath, src, null /*transform*/);
}
@LayoutlibDelegate
/*package*/ static void native_addPath(int nPath, int src, int matrix) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.addPath is not supported.", null, null /*data*/);
+ Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
+ if (matrixDelegate == null) {
+ return;
+ }
+
+ addPath(nPath, src, matrixDelegate.getAffineTransform());
}
@LayoutlibDelegate
@@ -487,6 +522,26 @@
return null;
}
+ private static void addPath(int destPath, int srcPath, AffineTransform transform) {
+ Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
+ if (destPathDelegate == null) {
+ return;
+ }
+
+ Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath);
+ if (srcPathDelegate == null) {
+ return;
+ }
+
+ if (transform != null) {
+ destPathDelegate.mPath.append(
+ srcPathDelegate.mPath.getPathIterator(transform), false);
+ } else {
+ destPathDelegate.mPath.append(srcPathDelegate.mPath, false);
+ }
+ }
+
+
/**
* Returns whether the path is empty.
* @return true if the path is empty.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index acc7379..e6e9647 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -192,7 +192,7 @@
Capability.UNBOUND_RENDERING,
Capability.CUSTOM_BACKGROUND_COLOR,
Capability.RENDER,
- Capability.LAYOUT_ONLY,
+ //Capability.LAYOUT_ONLY, // disable to run on ADT 10.0 which doesn't include this.
Capability.EMBEDDED_LAYOUT,
Capability.VIEW_MANIPULATION,
Capability.PLAY_ANIMATION,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index c1d7600..138a455 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -412,9 +412,7 @@
return LayoutParams.MATCH_PARENT;
} else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
return LayoutParams.WRAP_CONTENT;
- }
-
- if (RenderResources.REFERENCE_NULL.equals(s)) {
+ } else if (RenderResources.REFERENCE_NULL.equals(s)) {
return defValue;
}
@@ -486,23 +484,32 @@
return LayoutParams.MATCH_PARENT;
} else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
return LayoutParams.WRAP_CONTENT;
- }
-
- if (RenderResources.REFERENCE_NULL.equals(s)) {
+ } else if (RenderResources.REFERENCE_NULL.equals(s)) {
return defValue;
}
- // FIXME huh?
+ if (ResourceHelper.stringToFloat(s, mValue)) {
+ float f = mValue.getDimension(mBridgeResources.mMetrics);
- float f = getDimension(index, defValue);
- final int res = (int)(f+0.5f);
- if (res != 0) return res;
- if (f == 0) return 0;
- if (f > 0) return 1;
+ if (f < 0) {
+ // negative values are not allowed in pixel dimensions
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Negative pixel dimension: " + s,
+ null, null /*data*/);
+ return defValue;
+ }
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Can't convert to dimension: " + Integer.toString(index),
- null, null /*data*/);
+ if (f == 0) return 0;
+ if (f < 1) return 1;
+
+ return (int)(f+0.5f);
+ }
+
+ // looks like we were unable to resolve the dimension value
+ Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+ String.format(
+ "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
+ s, mNames[index]), null /*data*/);
return defValue;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 69f46e6..649160e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -377,7 +377,7 @@
}
// check the first character
- if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.') {
+ if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.' && buf[0] != '-') {
return false;
}