summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--cmds/installd/commands.c8
-rw-r--r--cmds/installd/installd.c78
-rw-r--r--cmds/installd/installd.h1
-rw-r--r--cmds/installd/utils.c39
-rw-r--r--core/java/android/os/Process.java2
-rw-r--r--core/java/android/view/GestureDetector.java118
-rw-r--r--core/java/android/view/View.java22
-rw-r--r--core/java/android/webkit/WebViewClassic.java14
-rw-r--r--core/java/android/widget/ViewAnimator.java15
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java2
-rw-r--r--core/res/AndroidManifest.xml7
-rw-r--r--core/res/res/drawable-nodpi/kg_widget_overscroll_layer_left.9.pngbin0 -> 2212 bytes
-rw-r--r--core/res/res/drawable-nodpi/kg_widget_overscroll_layer_right.9.pngbin0 -> 1451 bytes
-rw-r--r--core/res/res/layout-land/keyguard_host_view.xml4
-rw-r--r--core/res/res/layout-sw600dp-land/keyguard_host_view.xml4
-rw-r--r--core/res/res/layout-sw600dp-port/keyguard_host_view.xml4
-rw-r--r--core/res/res/layout/keyguard_selector_view.xml4
-rw-r--r--core/res/res/layout/keyguard_status_view.xml145
-rw-r--r--core/res/res/values/dimens.xml2
-rw-r--r--core/res/res/values/public.xml5
-rwxr-xr-xcore/res/res/values/strings.xml5
-rw-r--r--libs/hwui/FontRenderer.cpp32
-rw-r--r--libs/hwui/FontRenderer.h9
-rw-r--r--libs/hwui/GradientCache.cpp10
-rw-r--r--libs/hwui/OpenGLRenderer.cpp107
-rw-r--r--libs/hwui/OpenGLRenderer.h5
-rw-r--r--libs/hwui/SkiaShader.cpp35
-rw-r--r--libs/hwui/SkiaShader.h7
-rw-r--r--packages/SystemUI/res/layout-sw600dp/navigation_bar.xml14
-rw-r--r--packages/SystemUI/res/layout/navigation_bar.xml16
-rw-r--r--packages/SystemUI/res/values/attrs.xml12
-rw-r--r--packages/SystemUI/res/values/config.xml4
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java125
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java23
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java9
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java49
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java96
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java (renamed from policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetView.java)57
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java34
-rw-r--r--services/java/com/android/server/net/LockdownVpnTracker.java37
45 files changed, 790 insertions, 395 deletions
diff --git a/api/current.txt b/api/current.txt
index f5e3966..7d1c203 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29583,6 +29583,7 @@ package android.widget {
public class ViewAnimator extends android.widget.FrameLayout {
ctor public ViewAnimator(android.content.Context);
ctor public ViewAnimator(android.content.Context, android.util.AttributeSet);
+ method public boolean getAnimateFirstView();
method public android.view.View getCurrentView();
method public int getDisplayedChild();
method public android.view.animation.Animation getInAnimation();
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index a52f74a..ab64747 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -241,7 +241,6 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
{
char src_data_dir[PKG_PATH_MAX];
char pkg_path[PKG_PATH_MAX];
- char media_path[PATH_MAX];
DIR *d;
struct dirent *de;
struct stat s;
@@ -250,9 +249,6 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
if (create_persona_path(src_data_dir, src_persona)) {
return -1;
}
- if (create_persona_media_path(media_path, (userid_t) target_persona) == -1) {
- return -1;
- }
d = opendir(src_data_dir);
if (d != NULL) {
@@ -281,10 +277,10 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
closedir(d);
}
- // ensure /data/media/<user_id> exists
- if (ensure_dir(media_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ if (ensure_media_user_dirs((userid_t) target_persona) == -1) {
return -1;
}
+
return 0;
}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index d51004a..d559639 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -333,19 +333,16 @@ int initialize_globals() {
int initialize_directories() {
int res = -1;
- int version = 0;
- FILE* file;
// Read current filesystem layout version to handle upgrade paths
char version_path[PATH_MAX];
- if (snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path) > PATH_MAX) {
- return -1;
- }
- file = fopen(version_path, "r");
- if (file != NULL) {
- fscanf(file, "%d", &version);
- fclose(file);
+ snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
+
+ int oldVersion;
+ if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
+ oldVersion = 0;
}
+ int version = oldVersion;
// /data/user
char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
@@ -376,16 +373,12 @@ int initialize_directories() {
}
}
- // /data/media/0
- char owner_media_dir[PATH_MAX];
- create_persona_media_path(owner_media_dir, 0);
-
if (version == 0) {
// Introducing multi-user, so migrate /data/media contents into /data/media/0
- ALOGD("Migrating /data/media for multi-user");
+ ALOGD("Upgrading /data/media for multi-user");
// Ensure /data/media
- if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
goto fail;
}
@@ -402,10 +395,14 @@ int initialize_directories() {
}
// Create /data/media again
- if (ensure_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
+ if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
goto fail;
}
+ // /data/media/0
+ char owner_media_dir[PATH_MAX];
+ snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
+
// Move any owner data into place
if (access(media_tmp_dir, F_OK) == 0) {
if (rename(media_tmp_dir, owner_media_dir) == -1) {
@@ -433,8 +430,7 @@ int initialize_directories() {
// /data/media/<user_id>
snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
- if (ensure_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
- ALOGE("Failed to ensure %s: %s", user_media_dir, strerror(errno));
+ if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
goto fail;
}
}
@@ -445,22 +441,46 @@ int initialize_directories() {
version = 1;
}
- // Ensure /data/media/0 is always ready
- if (ensure_dir(owner_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
- goto fail;
+ // /data/media/obb
+ char media_obb_dir[PATH_MAX];
+ snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
+
+ if (version == 1) {
+ // Introducing /data/media/obb for sharing OBB across users; migrate
+ // any existing OBB files from owner.
+ ALOGD("Upgrading to shared /data/media/obb");
+
+ // /data/media/0/Android/obb
+ char owner_obb_path[PATH_MAX];
+ snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
+
+ // Only move if target doesn't already exist
+ if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
+ if (rename(owner_obb_path, media_obb_dir) == -1) {
+ ALOGE("Failed to move OBB from owner: %s", strerror(errno));
+ goto fail;
+ }
+ }
+
+ version = 2;
}
- // Persist our current version
- file = fopen(version_path, "w");
- if (file != NULL) {
- fprintf(file, "%d", version);
- fsync(fileno(file));
- fclose(file);
- } else {
- ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
+ if (ensure_media_user_dirs(0) == -1) {
+ ALOGE("Failed to setup media for user 0");
+ goto fail;
+ }
+ if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
goto fail;
}
+ // Persist layout version if changed
+ if (version != oldVersion) {
+ if (fs_write_atomic_int(version_path, version) == -1) {
+ ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
+ goto fail;
+ }
+ }
+
// Success!
res = 0;
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 3201427..5b81d2c 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/wait.h>
+#include <cutils/fs.h>
#include <cutils/sockets.h>
#include <cutils/log.h>
#include <cutils/properties.h>
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 80247f1..625a35e 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -991,39 +991,14 @@ char *build_string3(char *s1, char *s2, char *s3) {
return result;
}
-/* Ensure that directory exists with given mode and owners. */
-int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) {
- // Check if path needs to be created
- struct stat sb;
- if (stat(path, &sb) == -1) {
- if (errno == ENOENT) {
- goto create;
- } else {
- ALOGE("Failed to stat(%s): %s", path, strerror(errno));
- return -1;
- }
- }
-
- // Exists, verify status
- if (sb.st_mode == mode || sb.st_uid == uid || sb.st_gid == gid) {
- return 0;
- } else {
- goto fixup;
- }
-
-create:
- if (mkdir(path, mode) == -1) {
- ALOGE("Failed to mkdir(%s): %s", path, strerror(errno));
- return -1;
- }
+/* Ensure that /data/media directories are prepared for given user. */
+int ensure_media_user_dirs(userid_t userid) {
+ char media_user_path[PATH_MAX];
+ char path[PATH_MAX];
-fixup:
- if (chown(path, uid, gid) == -1) {
- ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno));
- return -1;
- }
- if (chmod(path, mode) == -1) {
- ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno));
+ // Ensure /data/media/<userid> exists
+ create_persona_media_path(media_user_path, userid);
+ if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
return -1;
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 851b8df..d5fca4d 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -584,6 +584,8 @@ public class Process {
}
if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
argsForZygote.add("--mount-external-multiuser");
+ } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ argsForZygote.add("--mount-external-multiuser-all");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 0114a41..23337f0 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -226,17 +226,12 @@ public class GestureDetector {
*/
private boolean mIsDoubleTapping;
- private float mLastMotionY;
- private float mLastMotionX;
+ private float mLastFocusX;
+ private float mLastFocusY;
+ private float mDownFocusX;
+ private float mDownFocusY;
private boolean mIsLongpressEnabled;
-
- /**
- * True if we are at a target API level of >= Froyo or the developer can
- * explicitly set it. If true, input events with > 1 pointer will be ignored
- * so we can work side by side with multitouch gesture detectors.
- */
- private boolean mIgnoreMultitouch;
/**
* Determines speed during touch scrolling
@@ -349,8 +344,16 @@ public class GestureDetector {
* @throws NullPointerException if {@code listener} is null.
*/
public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
- this(context, listener, handler, context != null &&
- context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO);
+ if (handler != null) {
+ mHandler = new GestureHandler(handler);
+ } else {
+ mHandler = new GestureHandler();
+ }
+ mListener = listener;
+ if (listener instanceof OnDoubleTapListener) {
+ setOnDoubleTapListener((OnDoubleTapListener) listener);
+ }
+ init(context);
}
/**
@@ -362,31 +365,19 @@ public class GestureDetector {
* @param listener the listener invoked for all the callbacks, this must
* not be null.
* @param handler the handler to use
- * @param ignoreMultitouch whether events involving more than one pointer should
- * be ignored.
*
* @throws NullPointerException if {@code listener} is null.
*/
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
- boolean ignoreMultitouch) {
- if (handler != null) {
- mHandler = new GestureHandler(handler);
- } else {
- mHandler = new GestureHandler();
- }
- mListener = listener;
- if (listener instanceof OnDoubleTapListener) {
- setOnDoubleTapListener((OnDoubleTapListener) listener);
- }
- init(context, ignoreMultitouch);
+ boolean unused) {
+ this(context, listener, handler);
}
- private void init(Context context, boolean ignoreMultitouch) {
+ private void init(Context context) {
if (mListener == null) {
throw new NullPointerException("OnGestureListener must not be null");
}
mIsLongpressEnabled = true;
- mIgnoreMultitouch = ignoreMultitouch;
// Fallback to support pre-donuts releases
int touchSlop, doubleTapSlop, doubleTapTouchSlop;
@@ -456,34 +447,40 @@ public class GestureDetector {
}
final int action = ev.getAction();
- final float y = ev.getY();
- final float x = ev.getX();
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
+ final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;
+ final int skipIndex = pointerUp ? ev.getActionIndex() : -1;
+
+ // Determine focal point
+ float sumX = 0, sumY = 0;
+ final int count = ev.getPointerCount();
+ for (int i = 0; i < count; i++) {
+ if (skipIndex == i) continue;
+ sumX += ev.getX(i);
+ sumY += ev.getY(i);
+ }
+ final int div = pointerUp ? count - 1 : count;
+ final float focusX = sumX / div;
+ final float focusY = sumY / div;
+
boolean handled = false;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
- if (mIgnoreMultitouch) {
- // Multitouch event - abort.
- cancel();
- }
+ mDownFocusX = mLastFocusX = focusX;
+ mDownFocusY = mLastFocusY = focusY;
+ // Cancel long press and taps
+ cancelTaps();
break;
case MotionEvent.ACTION_POINTER_UP:
- // Ending a multitouch gesture and going back to 1 finger
- if (mIgnoreMultitouch && ev.getPointerCount() == 2) {
- int index = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
- mLastMotionX = ev.getX(index);
- mLastMotionY = ev.getY(index);
- mVelocityTracker.recycle();
- mVelocityTracker = VelocityTracker.obtain();
- }
+ mDownFocusX = mLastFocusX = focusX;
+ mDownFocusY = mLastFocusY = focusY;
break;
case MotionEvent.ACTION_DOWN:
@@ -504,8 +501,8 @@ public class GestureDetector {
}
}
- mLastMotionX = x;
- mLastMotionY = y;
+ mDownFocusX = mLastFocusX = focusX;
+ mDownFocusY = mLastFocusY = focusY;
if (mCurrentDownEvent != null) {
mCurrentDownEvent.recycle();
}
@@ -525,22 +522,22 @@ public class GestureDetector {
break;
case MotionEvent.ACTION_MOVE:
- if (mInLongPress || (mIgnoreMultitouch && ev.getPointerCount() > 1)) {
+ if (mInLongPress) {
break;
}
- final float scrollX = mLastMotionX - x;
- final float scrollY = mLastMotionY - y;
+ final float scrollX = mLastFocusX - focusX;
+ final float scrollY = mLastFocusY - focusY;
if (mIsDoubleTapping) {
// Give the move events of the double-tap
handled |= mDoubleTapListener.onDoubleTapEvent(ev);
} else if (mAlwaysInTapRegion) {
- final int deltaX = (int) (x - mCurrentDownEvent.getX());
- final int deltaY = (int) (y - mCurrentDownEvent.getY());
+ final int deltaX = (int) (focusX - mDownFocusX);
+ final int deltaY = (int) (focusY - mDownFocusY);
int distance = (deltaX * deltaX) + (deltaY * deltaY);
if (distance > mTouchSlopSquare) {
handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
- mLastMotionX = x;
- mLastMotionY = y;
+ mLastFocusX = focusX;
+ mLastFocusY = focusY;
mAlwaysInTapRegion = false;
mHandler.removeMessages(TAP);
mHandler.removeMessages(SHOW_PRESS);
@@ -551,8 +548,8 @@ public class GestureDetector {
}
} else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
- mLastMotionX = x;
- mLastMotionY = y;
+ mLastFocusX = focusX;
+ mLastFocusY = focusY;
}
break;
@@ -571,9 +568,10 @@ public class GestureDetector {
// A fling must travel the minimum tap distance
final VelocityTracker velocityTracker = mVelocityTracker;
+ final int pointerId = ev.getPointerId(0);
velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
- final float velocityY = velocityTracker.getYVelocity();
- final float velocityX = velocityTracker.getXVelocity();
+ final float velocityY = velocityTracker.getYVelocity(pointerId);
+ final float velocityX = velocityTracker.getXVelocity(pointerId);
if ((Math.abs(velocityY) > mMinimumFlingVelocity)
|| (Math.abs(velocityX) > mMinimumFlingVelocity)){
@@ -622,6 +620,18 @@ public class GestureDetector {
}
}
+ private void cancelTaps() {
+ mHandler.removeMessages(SHOW_PRESS);
+ mHandler.removeMessages(LONG_PRESS);
+ mHandler.removeMessages(TAP);
+ mIsDoubleTapping = false;
+ mAlwaysInTapRegion = false;
+ mAlwaysInBiggerTapRegion = false;
+ if (mInLongPress) {
+ mInLongPress = false;
+ }
+ }
+
private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
MotionEvent secondDown) {
if (!mAlwaysInBiggerTapRegion) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6ce73e1..745e1b8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17625,23 +17625,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// use use a height of 1, and then wack the matrix each time we
// actually use it.
shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
-
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+
this.host = host;
}
public void setFadeColor(int color) {
- if (color != 0 && color != mLastColor) {
+ if (color != mLastColor) {
mLastColor = color;
- color |= 0xFF000000;
-
- shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
- color & 0x00FFFFFF, Shader.TileMode.CLAMP);
- paint.setShader(shader);
- // Restore the default transfer mode (src_over)
- paint.setXfermode(null);
+ if (color != 0) {
+ shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
+ color & 0x00FFFFFF, Shader.TileMode.CLAMP);
+ paint.setShader(shader);
+ // Restore the default transfer mode (src_over)
+ paint.setXfermode(null);
+ } else {
+ shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
+ paint.setShader(shader);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ }
}
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index e16dd06..591b87f 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -687,6 +687,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// It's used to dismiss the dialog in destroy if not done before.
private AlertDialog mListBoxDialog = null;
+ // Reference to the save password dialog so it can be dimissed in
+ // destroy if not done before.
+ private AlertDialog mSavePasswordDialog = null;
+
static final String LOGTAG = "webview";
private ZoomManager mZoomManager;
@@ -1836,7 +1840,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
neverRemember.getData().putString("password", password);
neverRemember.obj = resumeMsg;
- new AlertDialog.Builder(mContext)
+ mSavePasswordDialog = new AlertDialog.Builder(mContext)
.setTitle(com.android.internal.R.string.save_password_label)
.setMessage(com.android.internal.R.string.save_password_message)
.setPositiveButton(com.android.internal.R.string.save_password_notnow,
@@ -1847,6 +1851,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
resumeMsg.sendToTarget();
mResumeMsg = null;
}
+ mSavePasswordDialog = null;
}
})
.setNeutralButton(com.android.internal.R.string.save_password_remember,
@@ -1857,6 +1862,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
remember.sendToTarget();
mResumeMsg = null;
}
+ mSavePasswordDialog = null;
}
})
.setNegativeButton(com.android.internal.R.string.save_password_never,
@@ -1867,6 +1873,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
neverRemember.sendToTarget();
mResumeMsg = null;
}
+ mSavePasswordDialog = null;
}
})
.setOnCancelListener(new OnCancelListener() {
@@ -1876,6 +1883,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
resumeMsg.sendToTarget();
mResumeMsg = null;
}
+ mSavePasswordDialog = null;
}
}).show();
// Return true so that WebViewCore will pause while the dialog is
@@ -2115,6 +2123,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mListBoxDialog.dismiss();
mListBoxDialog = null;
}
+ if (mSavePasswordDialog != null) {
+ mSavePasswordDialog.dismiss();
+ mSavePasswordDialog = null;
+ }
if (mWebViewCore != null) {
// Tell WebViewCore to destroy itself
synchronized (this) {
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index 6a68240..eee914e 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -329,8 +329,21 @@ public class ViewAnimator extends FrameLayout {
}
/**
+ * Returns whether the current View should be animated the first time the ViewAnimator
+ * is displayed.
+ *
+ * @return true if the current View will be animated the first time it is displayed,
+ * false otherwise.
+ *
+ * @see #setAnimateFirstView(boolean)
+ */
+ public boolean getAnimateFirstView() {
+ return mAnimateFirstTime;
+ }
+
+ /**
* Indicates whether the current View should be animated the first time
- * the ViewAnimation is displayed.
+ * the ViewAnimator is displayed.
*
* @param animate True to animate the current View the first time it is displayed,
* false otherwise.
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index d6f1807..d24513a 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -529,6 +529,8 @@ class ZygoteConnection {
niceName = arg.substring(arg.indexOf('=') + 1);
} else if (arg.equals("--mount-external-multiuser")) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
+ } else if (arg.equals("--mount-external-multiuser-all")) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else {
break;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 96eb54a..abb9c0f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -725,6 +725,13 @@
android:description="@string/permdesc_mediaStorageWrite"
android:protectionLevel="signature|system" />
+ <!-- Allows an application to access all multi-user external storage @hide -->
+ <permission android:name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE"
+ android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
+ android:label="@string/permlab_sdcardAccessAll"
+ android:description="@string/permdesc_sdcardAccessAll"
+ android:protectionLevel="signature" />
+
<!-- ============================================ -->
<!-- Permissions for low-level system interaction -->
<!-- ============================================ -->
diff --git a/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_left.9.png b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_left.9.png
new file mode 100644
index 0000000..c30eb1c
--- /dev/null
+++ b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_left.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_right.9.png b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_right.9.png
new file mode 100644
index 0000000..e5d5771
--- /dev/null
+++ b/core/res/res/drawable-nodpi/kg_widget_overscroll_layer_right.9.png
Binary files differ
diff --git a/core/res/res/layout-land/keyguard_host_view.xml b/core/res/res/layout-land/keyguard_host_view.xml
index ca0fa1d..b404155 100644
--- a/core/res/res/layout-land/keyguard_host_view.xml
+++ b/core/res/res/layout-land/keyguard_host_view.xml
@@ -26,7 +26,7 @@
android:layout_height="match_parent"
android:orientation="horizontal">
- <com.android.internal.policy.impl.keyguard.KeyguardWidgetView
+ <com.android.internal.policy.impl.keyguard.KeyguardWidgetPager
android:id="@+id/app_widget_container"
android:layout_width="0dip"
android:layout_height="match_parent"
@@ -35,8 +35,8 @@
<!-- TODO: Remove this once supported as a widget -->
<include layout="@layout/keyguard_status_view"/>
+ </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
- </com.android.internal.policy.impl.keyguard.KeyguardWidgetView>
<ViewFlipper
android:id="@+id/view_flipper"
diff --git a/core/res/res/layout-sw600dp-land/keyguard_host_view.xml b/core/res/res/layout-sw600dp-land/keyguard_host_view.xml
index c552885..e77f584 100644
--- a/core/res/res/layout-sw600dp-land/keyguard_host_view.xml
+++ b/core/res/res/layout-sw600dp-land/keyguard_host_view.xml
@@ -26,7 +26,7 @@
android:layout_height="match_parent"
android:orientation="horizontal">
- <com.android.internal.policy.impl.keyguard.KeyguardWidgetView
+ <com.android.internal.policy.impl.keyguard.KeyguardWidgetPager
android:id="@+id/app_widget_container"
android:layout_width="0dip"
android:layout_height="match_parent"
@@ -36,7 +36,7 @@
<!-- TODO: Remove this once supported as a widget -->
<include layout="@layout/keyguard_status_view"/>
- </com.android.internal.policy.impl.keyguard.KeyguardWidgetView>
+ </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
<FrameLayout
android:layout_width="0dip"
diff --git a/core/res/res/layout-sw600dp-port/keyguard_host_view.xml b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
index 675b69b..50636f1 100644
--- a/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
+++ b/core/res/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -28,7 +28,7 @@
android:gravity="center_horizontal"
android:clipChildren="false">
- <com.android.internal.policy.impl.keyguard.KeyguardWidgetView
+ <com.android.internal.policy.impl.keyguard.KeyguardWidgetPager
android:id="@+id/app_widget_container"
android:layout_width="match_parent"
android:layout_height="0dip"
@@ -38,7 +38,7 @@
<!-- TODO: Remove this once supported as a widget -->
<include layout="@layout/keyguard_status_view"/>
- </com.android.internal.policy.impl.keyguard.KeyguardWidgetView>
+ </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
<ViewFlipper
android:id="@+id/view_flipper"
diff --git a/core/res/res/layout/keyguard_selector_view.xml b/core/res/res/layout/keyguard_selector_view.xml
index 6f6611d..d516369 100644
--- a/core/res/res/layout/keyguard_selector_view.xml
+++ b/core/res/res/layout/keyguard_selector_view.xml
@@ -26,7 +26,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <com.android.internal.policy.impl.keyguard.KeyguardWidgetView
+ <com.android.internal.policy.impl.keyguard.KeyguardWidgetPager
android:id="@+id/app_widget_container"
android:layout_width="match_parent"
android:layout_height="0dip"
@@ -34,7 +34,7 @@
android:visibility="gone">
<!-- TODO: Remove this once supported as a widget -->
<include layout="@layout/keyguard_status_view"/>
- </com.android.internal.policy.impl.keyguard.KeyguardWidgetView>
+ </com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
<RelativeLayout
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/keyguard_status_view.xml b/core/res/res/layout/keyguard_status_view.xml
index 3560ea2..f8d05b7 100644
--- a/core/res/res/layout/keyguard_status_view.xml
+++ b/core/res/res/layout/keyguard_status_view.xml
@@ -18,97 +18,102 @@
-->
<!-- This is a view that shows general status information in Keyguard. -->
-<com.android.internal.policy.impl.keyguard.KeyguardStatusView
+<com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame
xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
- <com.android.internal.widget.DigitalClock android:id="@+id/time"
- android:layout_marginTop="@*android:dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
- android:layout_marginBottom="12dip"
- android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
- android:layout_gravity="end">
+ <com.android.internal.policy.impl.keyguard.KeyguardStatusView
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal">
- <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
- top of the other. Hence the redundant layout... -->
- <TextView android:id="@*android:id/timeDisplayBackground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@*android:color/lockscreen_clock_background"
- />
+ <com.android.internal.widget.DigitalClock android:id="@+id/time"
+ android:layout_marginTop="@*android:dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
+ android:layout_marginBottom="12dip"
+ android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
+ android:layout_gravity="end">
- <TextView android:id="@*android:id/timeDisplayForeground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@*android:color/lockscreen_clock_foreground"
- android:layout_alignStart="@*android:id/timeDisplayBackground"
- android:layout_alignTop="@*android:id/timeDisplayBackground"
- />
+ <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+ top of the other. Hence the redundant layout... -->
+ <TextView android:id="@*android:id/timeDisplayBackground"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@*android:color/lockscreen_clock_background"
+ />
+
+ <TextView android:id="@*android:id/timeDisplayForeground"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textSize="@*android:dimen/keyguard_lockscreen_clock_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@*android:color/lockscreen_clock_foreground"
+ android:layout_alignStart="@*android:id/timeDisplayBackground"
+ android:layout_alignTop="@*android:id/timeDisplayBackground"
+ />
+
+ </com.android.internal.widget.DigitalClock>
- </com.android.internal.widget.DigitalClock>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_gravity="end"
+ android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_gravity="end"
- android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin">
+ <TextView
+ android:id="@*android:id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+ />
+
+ <TextView
+ android:id="@*android:id/alarm_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ />
+
+ </LinearLayout>
<TextView
- android:id="@*android:id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:id="@*android:id/status1"
+ android:layout_gravity="end"
+ android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
/>
<TextView
- android:id="@*android:id/alarm_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
+ android:id="@*android:id/carrier"
+ android:layout_gravity="end"
+ android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
- android:drawablePadding="4dip"
+ android:textColor="?android:attr/textColorSecondary"
/>
- </LinearLayout>
-
- <TextView
- android:id="@*android:id/status1"
- android:layout_gravity="end"
- android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
- android:drawablePadding="4dip"
- />
-
- <TextView
- android:id="@*android:id/carrier"
- android:layout_gravity="end"
- android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
- />
-
-</com.android.internal.policy.impl.keyguard.KeyguardStatusView>
-
+ </com.android.internal.policy.impl.keyguard.KeyguardStatusView>
+</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame> \ No newline at end of file
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index cc4d05a..372a1ee 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -251,4 +251,6 @@
<!-- Height of widget view in keyguard. -->
<dimen name="kg_widget_view_height">0dp</dimen>
+ <!-- Padding surrounding each widget page -->
+ <dimen name="kg_widget_page_padding">10dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b110a40..6414df8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1237,6 +1237,7 @@
<java-symbol type="dimen" name="navigation_bar_height_landscape" />
<java-symbol type="dimen" name="navigation_bar_width" />
<java-symbol type="dimen" name="status_bar_height" />
+ <java-symbol type="dimen" name="kg_widget_page_padding" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
<java-symbol type="drawable" name="ic_jog_dial_unlock" />
@@ -1254,6 +1255,8 @@
<java-symbol type="drawable" name="jog_tab_target_yellow" />
<java-symbol type="drawable" name="menu_background" />
<java-symbol type="drawable" name="stat_sys_secure" />
+ <java-symbol type="drawable" name="kg_widget_overscroll_layer_left" />
+ <java-symbol type="drawable" name="kg_widget_overscroll_layer_right" />
<java-symbol type="id" name="action_mode_bar_stub" />
<java-symbol type="id" name="alarm_status" />
<java-symbol type="id" name="backspace" />
@@ -3749,5 +3752,5 @@
<public type="attr" name="listPreferredItemPaddingStart" />
<public type="attr" name="listPreferredItemPaddingEnd" />
<public type="attr" name="singleUser" />
-
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b0437a2..3178af0 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1616,6 +1616,11 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
<string name="permdesc_mediaStorageWrite" product="default">Allows the app to modify the contents of the internal media storage.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <string name="permlab_sdcardAccessAll">access external storage of all users</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_sdcardAccessAll">Allows the app to access external storage for all users.</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_cache_filesystem">access the cache filesystem</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 27e198c..6b08e7f 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -328,19 +328,19 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float
glyph->mCacheTexture);
}
-CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
+CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching) {
CachedGlyphInfo* cachedGlyph = NULL;
ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
if (index >= 0) {
cachedGlyph = mCachedGlyphs.valueAt(index);
} else {
- cachedGlyph = cacheGlyph(paint, textUnit);
+ cachedGlyph = cacheGlyph(paint, textUnit, precaching);
}
// Is the glyph still in texture cache?
if (!cachedGlyph->mIsValid) {
const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit);
- updateGlyphCache(paint, skiaGlyph, cachedGlyph);
+ updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching);
}
return cachedGlyph;
@@ -438,7 +438,7 @@ void Font::precache(SkPaint* paint, const char* text, int numGlyphs) {
break;
}
- CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
+ CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph, true);
glyphsCount++;
}
@@ -529,7 +529,8 @@ void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len
}
}
-void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph) {
+void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,
+ bool precaching) {
glyph->mAdvanceX = skiaGlyph.fAdvanceX;
glyph->mAdvanceY = skiaGlyph.fAdvanceY;
glyph->mBitmapLeft = skiaGlyph.fLeft;
@@ -542,7 +543,7 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
// Get the bitmap for the glyph
paint->findImage(skiaGlyph);
- mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY);
+ mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching);
if (!glyph->mIsValid) {
return;
@@ -567,7 +568,7 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
mState->mUploadTexture = true;
}
-CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) {
+CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching) {
CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
mCachedGlyphs.add(glyph, newGlyph);
@@ -575,7 +576,7 @@ CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) {
newGlyph->mGlyphIndex = skiaGlyph.fID;
newGlyph->mIsValid = false;
- updateGlyphCache(paint, skiaGlyph, newGlyph);
+ updateGlyphCache(paint, skiaGlyph, newGlyph, precaching);
return newGlyph;
}
@@ -762,7 +763,7 @@ CacheTexture* FontRenderer::cacheBitmapInTexture(const SkGlyph& glyph,
}
void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
- uint32_t* retOriginX, uint32_t* retOriginY) {
+ uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) {
checkInit();
cachedGlyph->mIsValid = false;
// If the glyph is too tall, don't cache it
@@ -779,15 +780,16 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
CacheTexture* cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
- // If the new glyph didn't fit, flush the state so far and invalidate everything
if (!cacheTexture) {
- flushAllAndInvalidate();
-
- // Try to fit it again
- cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
+ if (!precaching) {
+ // If the new glyph didn't fit and we are not just trying to precache it,
+ // clear out the cache and try again
+ flushAllAndInvalidate();
+ cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
+ }
- // if we still don't fit, something is wrong and we shouldn't draw
if (!cacheTexture) {
+ // either the glyph didn't fit or we're precaching and will cache it when we draw
return;
}
}
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index febae17..8d0d21d 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -243,8 +243,9 @@ protected:
void invalidateTextureCache(CacheTexture *cacheTexture = NULL);
- CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
- void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
+ CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching);
+ void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,
+ bool precaching);
void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
@@ -258,7 +259,7 @@ protected:
void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
- CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
+ CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching = false);
static glyph_t nextGlyph(const uint16_t** srcPtr) {
const uint16_t* src = *srcPtr;
@@ -364,7 +365,7 @@ protected:
void initTextTexture();
CacheTexture* createCacheTexture(int width, int height, bool allocate);
void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
- uint32_t *retOriginX, uint32_t *retOriginY);
+ uint32_t *retOriginX, uint32_t *retOriginY, bool precaching);
CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
void flushAllAndInvalidate();
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 726b57c7..2e4e349 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -217,10 +217,12 @@ void GradientCache::generateTexture(uint32_t* colors, float* positions,
float amount = (pos - start) / distance;
float oppAmount = 1.0f - amount;
- *p++ = uint8_t(startR * oppAmount + endR * amount);
- *p++ = uint8_t(startG * oppAmount + endG * amount);
- *p++ = uint8_t(startB * oppAmount + endB * amount);
- *p++ = uint8_t(startA * oppAmount + endA * amount);
+ const float alpha = startA * oppAmount + endA * amount;
+ const float a = alpha / 255.0f;
+ *p++ = uint8_t(a * (startR * oppAmount + endR * amount));
+ *p++ = uint8_t(a * (startG * oppAmount + endG * amount));
+ *p++ = uint8_t(a * (startB * oppAmount + endB * amount));
+ *p++ = uint8_t(alpha);
}
for (int i = 1; i < GRADIENT_TEXTURE_HEIGHT; i++) {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 09dbf78..8da9f66 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -440,7 +440,7 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
mode = SkXfermode::kSrcOver_Mode;
}
- createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags, previousFbo);
+ createLayer(left, top, right, bottom, alpha, mode, flags, previousFbo);
}
return count;
@@ -508,44 +508,56 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot
* buffer is left untouched until the first drawing operation. Only when
* something actually gets drawn are the layers regions cleared.
*/
-bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
- float right, float bottom, int alpha, SkXfermode::Mode mode,
- int flags, GLuint previousFbo) {
+bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
+ int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo) {
LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
// Window coordinates of the layer
+ Rect clip;
Rect bounds(left, top, right, bottom);
- if (!fboLayer) {
- mSnapshot->transform->mapRect(bounds);
-
- // Layers only make sense if they are in the framebuffer's bounds
- if (bounds.intersect(*snapshot->clipRect)) {
- // We cannot work with sub-pixels in this case
- bounds.snapToPixelBoundaries();
-
- // When the layer is not an FBO, we may use glCopyTexImage so we
- // need to make sure the layer does not extend outside the bounds
- // of the framebuffer
- if (!bounds.intersect(snapshot->previous->viewport)) {
- bounds.setEmpty();
- }
- } else {
+ Rect untransformedBounds(bounds);
+ mSnapshot->transform->mapRect(bounds);
+
+ // Layers only make sense if they are in the framebuffer's bounds
+ if (bounds.intersect(*mSnapshot->clipRect)) {
+ // We cannot work with sub-pixels in this case
+ bounds.snapToPixelBoundaries();
+
+ // When the layer is not an FBO, we may use glCopyTexImage so we
+ // need to make sure the layer does not extend outside the bounds
+ // of the framebuffer
+ if (!bounds.intersect(mSnapshot->previous->viewport)) {
bounds.setEmpty();
+ } else if (fboLayer) {
+ clip.set(bounds);
+ mat4 inverse;
+ inverse.loadInverse(*mSnapshot->transform);
+ inverse.mapRect(clip);
+ clip.snapToPixelBoundaries();
+ if (clip.intersect(untransformedBounds)) {
+ clip.translate(-left, -top);
+ bounds.set(untransformedBounds);
+ } else {
+ clip.setEmpty();
+ }
}
+ } else {
+ bounds.setEmpty();
}
if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
- bounds.getHeight() > mCaches.maxTextureSize) {
- snapshot->empty = fboLayer;
+ bounds.getHeight() > mCaches.maxTextureSize ||
+ (fboLayer && clip.isEmpty())) {
+ mSnapshot->empty = fboLayer;
} else {
- snapshot->invisible = snapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
+ mSnapshot->invisible = mSnapshot->invisible || (alpha <= ALPHA_THRESHOLD && fboLayer);
}
// Bail out if we won't draw in this snapshot
- if (snapshot->invisible || snapshot->empty) {
+ if (mSnapshot->invisible || mSnapshot->empty) {
return false;
}
@@ -563,23 +575,23 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
layer->setBlend(true);
// Save the layer in the snapshot
- snapshot->flags |= Snapshot::kFlagIsLayer;
- snapshot->layer = layer;
+ mSnapshot->flags |= Snapshot::kFlagIsLayer;
+ mSnapshot->layer = layer;
if (fboLayer) {
- return createFboLayer(layer, bounds, snapshot, previousFbo);
+ return createFboLayer(layer, bounds, clip, previousFbo);
} else {
// Copy the framebuffer into the layer
layer->bindTexture();
if (!bounds.isEmpty()) {
if (layer->isEmpty()) {
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
- bounds.left, snapshot->height - bounds.bottom,
+ bounds.left, mSnapshot->height - bounds.bottom,
layer->getWidth(), layer->getHeight(), 0);
layer->setEmpty(false);
} else {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
- snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
+ mSnapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
}
// Enqueue the buffer coordinates to clear the corresponding region later
@@ -590,35 +602,20 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
return true;
}
-bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
- GLuint previousFbo) {
+bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLuint previousFbo) {
layer->setFbo(mCaches.fboCache.get());
- snapshot->region = &snapshot->layer->region;
- snapshot->flags |= Snapshot::kFlagFboTarget;
-
- Rect clip(bounds);
- snapshot->transform->mapRect(clip);
- clip.intersect(*snapshot->clipRect);
- clip.snapToPixelBoundaries();
- clip.intersect(snapshot->previous->viewport);
-
- mat4 inverse;
- inverse.loadInverse(*mSnapshot->transform);
-
- inverse.mapRect(clip);
- clip.snapToPixelBoundaries();
- clip.intersect(bounds);
- clip.translate(-bounds.left, -bounds.top);
-
- snapshot->flags |= Snapshot::kFlagIsFboLayer;
- snapshot->fbo = layer->getFbo();
- snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
- snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
- snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
- snapshot->height = bounds.getHeight();
- snapshot->flags |= Snapshot::kFlagDirtyOrtho;
- snapshot->orthoMatrix.load(mOrthoMatrix);
+ mSnapshot->region = &mSnapshot->layer->region;
+ mSnapshot->flags |= Snapshot::kFlagFboTarget;
+
+ mSnapshot->flags |= Snapshot::kFlagIsFboLayer;
+ mSnapshot->fbo = layer->getFbo();
+ mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
+ mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
+ mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
+ mSnapshot->height = bounds.getHeight();
+ mSnapshot->flags |= Snapshot::kFlagDirtyOrtho;
+ mSnapshot->orthoMatrix.load(mOrthoMatrix);
// Bind texture to FBO
glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index d3b98a4..2369f47 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -380,7 +380,7 @@ private:
*
* @return True if the layer was successfully created, false otherwise
*/
- bool createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom,
+ bool createLayer(float left, float top, float right, float bottom,
int alpha, SkXfermode::Mode mode, int flags, GLuint previousFbo);
/**
@@ -391,8 +391,7 @@ private:
* @param bounds The bounds of the layer
* @param previousFbo The name of the current framebuffer
*/
- bool createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
- GLuint previousFbo);
+ bool createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLuint previousFbo);
/**
* Compose the specified layer as a region.
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 8916efd..9013fd5 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -46,11 +46,12 @@ static inline bool isPowerOfTwo(unsigned int n) {
}
static inline void bindUniformColor(int slot, uint32_t color) {
+ const float a = ((color >> 24) & 0xff) / 255.0f;
glUniform4f(slot,
- ((color >> 16) & 0xff) / 255.0f,
- ((color >> 8) & 0xff) / 255.0f,
- ((color ) & 0xff) / 255.0f,
- ((color >> 24) & 0xff) / 255.0f);
+ a * ((color >> 16) & 0xff) / 255.0f,
+ a * ((color >> 8) & 0xff) / 255.0f,
+ a * ((color ) & 0xff) / 255.0f,
+ a);
}
///////////////////////////////////////////////////////////////////////////////
@@ -154,10 +155,6 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
// Uniforms
bindTexture(texture, mWrapS, mWrapT);
- // Assume linear here; we should really check the transform in
- // ::updateTransforms() but we don't have the texture object
- // available at that point. The optimization is not worth the
- // effort for now.
texture->setFilter(GL_LINEAR);
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
@@ -166,14 +163,6 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
}
-void SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView,
- const Snapshot& snapshot) {
- mat4 textureTransform;
- computeScreenSpaceMatrix(textureTransform, modelView);
- glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
- GL_FALSE, &textureTransform.data[0]);
-}
-
///////////////////////////////////////////////////////////////////////////////
// Linear gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -257,13 +246,6 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}
-void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& modelView,
- const Snapshot& snapshot) {
- mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
- glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
-
///////////////////////////////////////////////////////////////////////////////
// Circular gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -384,13 +366,6 @@ void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelVi
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}
-void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView,
- const Snapshot& snapshot) {
- mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
- glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
-
///////////////////////////////////////////////////////////////////////////////
// Compose shader
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index a710b86..2687592 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -82,10 +82,6 @@ struct SkiaShader {
mGradientCache = gradientCache;
}
- virtual void updateTransforms(Program* program, const mat4& modelView,
- const Snapshot& snapshot) {
- }
-
uint32_t getGenerationId() {
return mGenerationId;
}
@@ -148,7 +144,6 @@ struct SkiaBitmapShader: public SkiaShader {
void describe(ProgramDescription& description, const Extensions& extensions);
void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
GLuint* textureUnit);
- void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
private:
SkiaBitmapShader() {
@@ -172,7 +167,6 @@ struct SkiaLinearGradientShader: public SkiaShader {
void describe(ProgramDescription& description, const Extensions& extensions);
void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
GLuint* textureUnit);
- void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
private:
SkiaLinearGradientShader() {
@@ -197,7 +191,6 @@ struct SkiaSweepGradientShader: public SkiaShader {
virtual void describe(ProgramDescription& description, const Extensions& extensions);
void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
GLuint* textureUnit);
- void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
protected:
SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 67e13eb..fbbd7e5 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -143,8 +143,13 @@
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
- android:layout_height="@dimen/navigation_bar_deadzone_size"
+ android:layout_height="match_parent"
android:layout_width="match_parent"
+ systemui:minSize="@dimen/navigation_bar_deadzone_size"
+ systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+ systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+ systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+ systemui:orientation="horizontal"
android:layout_gravity="top"
/>
</FrameLayout>
@@ -269,8 +274,13 @@
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
- android:layout_height="@dimen/navigation_bar_deadzone_size"
+ android:layout_height="match_parent"
android:layout_width="match_parent"
+ systemui:minSize="@dimen/navigation_bar_deadzone_size"
+ systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+ systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+ systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+ systemui:orientation="vertical"
android:layout_gravity="top"
/>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index d41040d..33b5dbb 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -147,8 +147,13 @@
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
- android:layout_height="@dimen/navigation_bar_deadzone_size"
+ android:layout_height="match_parent"
android:layout_width="match_parent"
+ systemui:minSize="@dimen/navigation_bar_deadzone_size"
+ systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+ systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+ systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+ systemui:orientation="horizontal"
android:layout_gravity="top"
/>
</FrameLayout>
@@ -276,9 +281,14 @@
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
- android:layout_width="@dimen/navigation_bar_deadzone_size"
android:layout_height="match_parent"
- android:layout_gravity="left"
+ android:layout_width="match_parent"
+ systemui:minSize="@dimen/navigation_bar_deadzone_size"
+ systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
+ systemui:holdTime="@integer/navigation_bar_deadzone_hold"
+ systemui:decayTime="@integer/navigation_bar_deadzone_decay"
+ systemui:orientation="vertical"
+ android:layout_gravity="top"
/>
</FrameLayout>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 48fb21f..047570f 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -35,5 +35,17 @@
<declare-styleable name="RecentsPanelView">
<attr name="recentItemLayout" format="reference" />
</declare-styleable>
+ <declare-styleable name="DeadZone">
+ <attr name="minSize" format="dimension" />
+ <attr name="maxSize" format="dimension" />
+ <attr name="holdTime" format="integer" />
+ <attr name="decayTime" format="integer" />
+ <attr name="orientation" />
+ </declare-styleable>
+
+ <attr name="orientation">
+ <enum name="horizontal" value="0" />
+ <enum name="vertical" value="1" />
+ </attr>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1cd7904..3337573 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -72,5 +72,9 @@
<!-- Whether we're using the tablet-optimized recents interface (we use this
value at runtime for some things) -->
<integer name="status_bar_recents_bg_gradient_degrees">90</integer>
+
+ <!-- decay duration (from size_max -> size), in ms -->
+ <integer name="navigation_bar_deadzone_hold">333</integer>
+ <integer name="navigation_bar_deadzone_decay">333</integer>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 94465e2..0d7cdb1 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -63,6 +63,8 @@
<!-- thickness (height) of the dead zone at the top of the navigation bar,
reducing false presses on navbar buttons; approx 2mm -->
<dimen name="navigation_bar_deadzone_size">12dp</dimen>
+ <!-- size of the dead zone when touches have recently occurred elsewhere on screen -->
+ <dimen name="navigation_bar_deadzone_size_max">32dp</dimen>
<!-- Height of notification icons in the status bar -->
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 33973b6..dcc2e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -45,13 +45,12 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.DelegateViewHelper;
+import com.android.systemui.statusbar.policy.DeadZone;
public class NavigationBarView extends LinearLayout {
final static boolean DEBUG = false;
final static String TAG = "PhoneStatusBar/NavigationBarView";
- final static boolean DEBUG_DEADZONE = false;
-
final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
@@ -71,6 +70,7 @@ public class NavigationBarView extends LinearLayout {
private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
private DelegateViewHelper mDelegateHelper;
+ private DeadZone mDeadZone;
// workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
final static boolean WORKAROUND_INVALID_LAYOUT = true;
@@ -109,10 +109,14 @@ public class NavigationBarView extends LinearLayout {
@Override
public boolean onTouchEvent(MotionEvent event) {
+ if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+ mDeadZone.poke(event);
+ }
if (mDelegateHelper != null) {
- mDelegateHelper.onInterceptTouchEvent(event);
+ boolean ret = mDelegateHelper.onInterceptTouchEvent(event);
+ if (ret) return true;
}
- return true;
+ return super.onTouchEvent(event);
}
@Override
@@ -335,15 +339,13 @@ public class NavigationBarView extends LinearLayout {
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
+ mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
+
// force the low profile & disabled states into compliance
setLowProfile(mLowProfile, false, true /* force */);
setDisabledFlags(mDisabledFlags, true /* force */);
setMenuVisibility(mShowMenu, true /* force */);
- if (DEBUG_DEADZONE) {
- mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
- }
-
if (DEBUG) {
Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 9d2678a..9b4ee38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -639,6 +639,7 @@ public class PhoneStatusBar extends BaseStatusBar {
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.OPAQUE);
// this will allow the navbar to run in an overlay on devices that support this
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 19fbe96..6ffca2a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -16,26 +16,145 @@
package com.android.systemui.statusbar.policy;
+import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import com.android.systemui.R;
public class DeadZone extends View {
+ public static final String TAG = "DeadZone";
+
+ public static final boolean DEBUG = false;
+ public static final int HORIZONTAL = 0;
+ public static final int VERTICAL = 1;
+
+ private boolean mShouldFlash;
+ private float mFlashFrac = 0f;
+
+ private int mSizeMax;
+ private int mSizeMin;
+ // Upon activity elsewhere in the UI, the dead zone will hold steady for
+ // mHold ms, then move back over the course of mDecay ms
+ private int mHold, mDecay;
+ private boolean mVertical;
+ private long mLastPokeTime;
+
+ private final Runnable mDebugFlash = new Runnable() {
+ @Override
+ public void run() {
+ ObjectAnimator.ofFloat(DeadZone.this, "flash", 1f, 0f).setDuration(150).start();
+ }
+ };
+
public DeadZone(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DeadZone(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeadZone,
+ defStyle, 0);
+
+ mHold = a.getInteger(R.styleable.DeadZone_holdTime, 0);
+ mDecay = a.getInteger(R.styleable.DeadZone_decayTime, 0);
+
+ mSizeMin = a.getDimensionPixelSize(R.styleable.DeadZone_minSize, 0);
+ mSizeMax = a.getDimensionPixelSize(R.styleable.DeadZone_maxSize, 0);
+
+ int index = a.getInt(R.styleable.DeadZone_orientation, -1);
+ mVertical = (index == VERTICAL);
+
+ if (DEBUG)
+ Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold
+ + (mVertical ? " vertical" : " horizontal"));
+
+ setFlashOnTouchCapture(true);
+ }
+
+ static float lerp(float a, float b, float f) {
+ return (b - a) * f + a;
+ }
+
+ private float getSize(long now) {
+ if (mSizeMax == 0)
+ return 0;
+ long dt = (now - mLastPokeTime);
+ if (dt > mHold + mDecay)
+ return mSizeMin;
+ if (dt < mHold)
+ return mSizeMax;
+ return (int) lerp(mSizeMax, mSizeMin, (float) (dt - mHold) / mDecay);
+ }
+
+ public void setFlashOnTouchCapture(boolean dbg) {
+ mShouldFlash = dbg;
+ mFlashFrac = 0f;
+ postInvalidate();
}
// I made you a touch event
@Override
- public boolean onTouchEvent (MotionEvent event) {
- return true; // but I eated it
+ public boolean onTouchEvent(MotionEvent event) {
+ if (DEBUG)
+ Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction()));
+
+ final int action = event.getAction();
+ if (action == MotionEvent.ACTION_OUTSIDE) {
+ poke(event);
+ } else if (action == MotionEvent.ACTION_DOWN) {
+ if (DEBUG)
+ Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
+ int size = (int) getSize(event.getEventTime());
+ if ((mVertical && event.getX() < size) || event.getY() < size) {
+ if (DEBUG)
+ Slog.v(TAG, "eating click!");
+ if (mShouldFlash) {
+ post(mDebugFlash);
+ postInvalidate();
+ }
+ return true; // but I eated it
+ }
+ }
+ return false;
+ }
+
+ public void poke(MotionEvent event) {
+ mLastPokeTime = event.getEventTime();
+ if (DEBUG)
+ Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
+ postInvalidate();
+ }
+
+ public void setFlash(float f) {
+ mFlashFrac = f;
+ postInvalidate();
}
-}
+ public float getFlash() {
+ return mFlashFrac;
+ }
+
+ @Override
+ public void onDraw(Canvas can) {
+ if (!mShouldFlash || mFlashFrac <= 0f) {
+ return;
+ }
+
+ final int size = (int) getSize(SystemClock.uptimeMillis());
+ can.clipRect(0, 0, mVertical ? size : can.getWidth(), mVertical ? can.getHeight() : size);
+ final float frac = DEBUG ? (mFlashFrac - 0.5f) + 0.5f : mFlashFrac;
+ can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA);
+
+ if (DEBUG && size > mSizeMin)
+ // crazy aggressive redrawing here, for debugging only
+ postInvalidateDelayed(100);
+ }
+}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ef31dd6..2b6e856 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3141,7 +3141,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void onServiceDisconnected(ComponentName name) {}
};
- if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
+ if (mContext.bindService(
+ intent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) {
mScreenshotConnection = conn;
mHandler.postDelayed(mScreenshotTimeout, 10000);
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index 0ad3a6a..d74a5e7 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -70,7 +70,7 @@ public class KeyguardHostView extends KeyguardViewBase {
private static final int SECURITY_ACCOUNT_ID = R.id.keyguard_account_view;
private AppWidgetHost mAppWidgetHost;
- private ViewGroup mAppWidgetContainer;
+ private KeyguardWidgetPager mAppWidgetContainer;
private ViewFlipper mViewFlipper;
private Button mEmergencyDialerButton;
private boolean mEnableMenuKey;
@@ -121,7 +121,7 @@ public class KeyguardHostView extends KeyguardViewBase {
@Override
protected void onFinishInflate() {
- mAppWidgetContainer = (ViewGroup) findViewById(R.id.app_widget_container);
+ mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
mAppWidgetContainer.setVisibility(VISIBLE);
// View Flipper
@@ -182,7 +182,7 @@ public class KeyguardHostView extends KeyguardViewBase {
}
void addWidget(AppWidgetHostView view) {
- mAppWidgetContainer.addView(view);
+ mAppWidgetContainer.addWidget(view);
}
private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
@@ -221,6 +221,11 @@ public class KeyguardHostView extends KeyguardViewBase {
mViewMediatorCallback.keyguardDoneDrawing();
}
+ @Override
+ public void setOnDismissRunnable(Runnable runnable) {
+ KeyguardHostView.this.setOnDismissRunnable(runnable);
+ }
+
};
public void takeEmergencyCallAction() {
@@ -273,7 +278,7 @@ public class KeyguardHostView extends KeyguardViewBase {
final android.app.PendingIntent pendingIntent,
final Intent fillInIntent) {
if (pendingIntent.isActivity()) {
- mLaunchRunnable = new Runnable() {
+ setOnDismissRunnable(new Runnable() {
public void run() {
try {
// TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
@@ -292,7 +297,7 @@ public class KeyguardHostView extends KeyguardViewBase {
"unknown exception: ", e);
}
}
- };
+ });
mCallback.dismiss(false);
return true;
@@ -307,6 +312,14 @@ public class KeyguardHostView extends KeyguardViewBase {
requestFocus();
}
+ /**
+ * Sets a runnable to run when keyguard is dismissed
+ * @param runnable
+ */
+ protected void setOnDismissRunnable(Runnable runnable) {
+ mLaunchRunnable = runnable;
+ }
+
private KeyguardSecurityView getSecurityView(int securitySelectorId) {
final int children = mViewFlipper.getChildCount();
for (int child = 0; child < children; child++) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java
index 1a4a40b..36342a5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java
@@ -57,6 +57,15 @@ public interface KeyguardSecurityCallback {
*/
void showBackupUnlock();
+ /**
+ * Used to inform keyguard when the current view is done drawing.
+ */
void keyguardDoneDrawing();
+ /**
+ * Sets a runnable to launch after the user enters their
+ * @param runnable
+ */
+ void setOnDismissRunnable(Runnable runnable);
+
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
index b69697f..a38b247 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -61,7 +61,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
.getAssistIntent(mContext, UserHandle.USER_CURRENT);
if (assistIntent != null) {
- launchActivity(assistIntent);
+ launchActivity(assistIntent, false);
} else {
Log.w(TAG, "Failed to get intent for assist activity");
}
@@ -69,7 +69,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
break;
case com.android.internal.R.drawable.ic_lockscreen_camera:
- launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA));
+ launchCamera();
mCallback.userActivity(0);
break;
@@ -128,6 +128,16 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
this(context, null);
}
+ protected void launchCamera() {
+ if (mLockPatternUtils.isSecure()) {
+ // Launch the secure version of the camera
+ launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE), true);
+ } else {
+ // Launch the normal camera
+ launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA), false);
+ }
+ }
+
public KeyguardSelectorView(Context context, AttributeSet attrs) {
super(context, attrs);
mLockPatternUtils = new LockPatternUtils(getContext());
@@ -217,21 +227,36 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
/**
* Launches the said intent for the current foreground user.
* @param intent
+ * @param showsWhileLocked true if the activity can be run on top of keyguard.
+ * See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED}
*/
- private void launchActivity(Intent intent) {
+ private void launchActivity(final Intent intent, boolean showsWhileLocked) {
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
- try {
- ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
- } catch (RemoteException e) {
- Log.w(TAG, "can't dismiss keyguard on launch");
- }
- try {
- mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "Activity not found for intent + " + intent.getAction());
+ boolean isSecure = mLockPatternUtils.isSecure();
+ if (!isSecure || showsWhileLocked) {
+ if (!isSecure) try {
+ ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+ } catch (RemoteException e) {
+ Log.w(TAG, "can't dismiss keyguard on launch");
+ }
+ try {
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "Activity not found for intent + " + intent.getAction());
+ }
+ } else {
+ // Create a runnable to start the activity and ask the user to enter their
+ // credentials.
+ mCallback.setOnDismissRunnable(new Runnable() {
+ @Override
+ public void run() {
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ }
+ });
+ mCallback.dismiss(false);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
new file mode 100644
index 0000000..d778129
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 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.internal.policy.impl.keyguard;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+
+public class KeyguardWidgetFrame extends FrameLayout {
+ private final static PorterDuffXfermode sAddBlendMode =
+ new PorterDuffXfermode(PorterDuff.Mode.ADD);
+ private static int sWidgetPagePadding;
+ private static Drawable sLeftOverscrollDrawable;
+ private static Drawable sRightOverscrollDrawable;
+
+ private Drawable mForegroundDrawable;
+ private final Rect mForegroundRect = new Rect();
+ private int mForegroundAlpha = 0;
+
+ public KeyguardWidgetFrame(Context context) {
+ this(context, null, 0);
+ }
+
+ public KeyguardWidgetFrame(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public KeyguardWidgetFrame(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ if (sLeftOverscrollDrawable == null) {
+ Resources res = context.getResources();
+ sLeftOverscrollDrawable = res.getDrawable(
+ com.android.internal.R.drawable.kg_widget_overscroll_layer_left);
+ sRightOverscrollDrawable = res.getDrawable(
+ com.android.internal.R.drawable.kg_widget_overscroll_layer_right);
+ sWidgetPagePadding =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.kg_widget_page_padding);
+ }
+ setPadding(sWidgetPagePadding, sWidgetPagePadding, sWidgetPagePadding, sWidgetPagePadding);
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ if (mForegroundAlpha > 0) {
+ mForegroundDrawable.setBounds(mForegroundRect);
+ Paint p = ((NinePatchDrawable) mForegroundDrawable).getPaint();
+ p.setXfermode(sAddBlendMode);
+ mForegroundDrawable.draw(canvas);
+ p.setXfermode(null);
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mForegroundRect.set(sWidgetPagePadding, sWidgetPagePadding,
+ w - sWidgetPagePadding, h - sWidgetPagePadding);
+ }
+
+ void setOverScrollAmount(float r, boolean left) {
+ if (left && mForegroundDrawable != sLeftOverscrollDrawable) {
+ mForegroundDrawable = sLeftOverscrollDrawable;
+ } else if (!left && mForegroundDrawable != sRightOverscrollDrawable) {
+ mForegroundDrawable = sRightOverscrollDrawable;
+ }
+
+ mForegroundAlpha = (int) Math.round((r * 255));
+ mForegroundDrawable.setAlpha(mForegroundAlpha);
+ invalidate();
+ }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
index 120f8f8..7d077e2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -16,39 +16,53 @@
package com.android.internal.policy.impl.keyguard;
import android.animation.TimeInterpolator;
+import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.Gravity;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
-public class KeyguardWidgetView extends PagedView {
+import android.widget.FrameLayout;
- public KeyguardWidgetView(Context context, AttributeSet attrs) {
+public class KeyguardWidgetPager extends PagedView {
+ ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
+ private static float CAMERA_DISTANCE = 10000;
+ private static float TRANSITION_SCALE_FACTOR = 0.74f;
+ private static float TRANSITION_PIVOT = 0.65f;
+ private static float TRANSITION_MAX_ROTATION = 30;
+ private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
+ private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
+ private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
+
+ public KeyguardWidgetPager(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
- public KeyguardWidgetView(Context context) {
+ public KeyguardWidgetPager(Context context) {
this(null, null, 0);
}
- public KeyguardWidgetView(Context context, AttributeSet attrs, int defStyle) {
+ public KeyguardWidgetPager(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
+ /*
+ * We wrap widgets in a special frame which handles drawing the overscroll foreground.
+ */
+ public void addWidget(AppWidgetHostView widget) {
+ KeyguardWidgetFrame frame = new KeyguardWidgetFrame(getContext());
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT);
+ lp.gravity = Gravity.CENTER;
+ // The framework adds a default padding to AppWidgetHostView. We don't need this padding
+ // for the Keyguard, so we override it to be 0.
+ widget.setPadding(0, 0, 0, 0);
+ frame.addView(widget, lp);
+ addView(frame);
}
- ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
- private static float CAMERA_DISTANCE = 1500;
- private static float TRANSITION_SCALE_FACTOR = 0.74f;
- private static float TRANSITION_PIVOT = 0.65f;
- private static float TRANSITION_MAX_ROTATION = 30;
- private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
- private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
- private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
/*
* This interpolator emulates the rate at which the perceived scale of an object changes
* as its distance from a camera increases. When this interpolator is applied to a scale
@@ -68,6 +82,11 @@ public class KeyguardWidgetView extends PagedView {
}
}
+ @Override
+ protected void overScroll(float amount) {
+ acceleratedOverScroll(amount);
+ }
+
// In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
@Override
protected void screenScrolled(int screenCenter) {
@@ -103,6 +122,10 @@ public class KeyguardWidgetView extends PagedView {
// Overscroll to the left
v.setPivotX(TRANSITION_PIVOT * pageWidth);
v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
+ if (v instanceof KeyguardWidgetFrame) {
+ ((KeyguardWidgetFrame) v).setOverScrollAmount(Math.abs(scrollProgress),
+ true);
+ }
scale = 1.0f;
alpha = 1.0f;
// On the first page, we don't want the page to have any lateral motion
@@ -113,6 +136,10 @@ public class KeyguardWidgetView extends PagedView {
v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
scale = 1.0f;
alpha = 1.0f;
+ if (v instanceof KeyguardWidgetFrame) {
+ ((KeyguardWidgetFrame) v).setOverScrollAmount(Math.abs(scrollProgress),
+ false);
+ }
// On the last page, we don't want the page to have any lateral motion.
translationX = 0;
} else {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d8c8dfa..a061d58 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1991,13 +1991,19 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
final PackageManager pm = mContext.getPackageManager();
gids = pm.getPackageGids(app.info.packageName);
+
+ if (Environment.isExternalStorageEmulated()) {
+ if (pm.checkPermission(
+ android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
+ app.info.packageName) == PERMISSION_GRANTED) {
+ mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
+ } else {
+ mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
+ }
+ }
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
-
- if (Environment.isExternalStorageEmulated()) {
- mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
- }
}
if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
@@ -10742,7 +10748,25 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("File descriptors passed in Intent");
}
- checkValidCaller(Binder.getCallingUid(), userId);
+ if (userId != UserHandle.getCallingUserId()) {
+ // Requesting a different user, make sure that they have permission
+ if (checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
+ == PackageManager.PERMISSION_GRANTED) {
+ // Translate to the current user id, if caller wasn't aware
+ if (userId == UserHandle.USER_CURRENT) {
+ userId = mCurrentUserId;
+ }
+ } else {
+ String msg = "Permission Denial: Request to bindService as user " + userId
+ + " but is calling from user " + UserHandle.getCallingUserId()
+ + "; this requires "
+ + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ }
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType,
diff --git a/services/java/com/android/server/net/LockdownVpnTracker.java b/services/java/com/android/server/net/LockdownVpnTracker.java
index 541650e..dabcf2f 100644
--- a/services/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/java/com/android/server/net/LockdownVpnTracker.java
@@ -55,6 +55,7 @@ public class LockdownVpnTracker {
private static final int MAX_ERROR_COUNT = 4;
private static final String ACTION_LOCKDOWN_RESET = "com.android.server.action.LOCKDOWN_RESET";
+ private static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS";
private final Context mContext;
private final INetworkManagementService mNetService;
@@ -84,9 +85,9 @@ public class LockdownVpnTracker {
mVpn = Preconditions.checkNotNull(vpn);
mProfile = Preconditions.checkNotNull(profile);
- final Intent intent = new Intent(ACTION_LOCKDOWN_RESET);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mResetIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ final Intent resetIntent = new Intent(ACTION_LOCKDOWN_RESET);
+ resetIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mResetIntent = PendingIntent.getBroadcast(mContext, 0, resetIntent, 0);
}
private BroadcastReceiver mResetReceiver = new BroadcastReceiver() {
@@ -115,7 +116,7 @@ public class LockdownVpnTracker {
final boolean egressChanged = egressProp == null
|| !TextUtils.equals(mAcceptedEgressIface, egressProp.getInterfaceName());
if (egressDisconnected || egressChanged) {
- clearSourceRules();
+ clearSourceRulesLocked();
mAcceptedEgressIface = null;
mVpn.stopLegacyVpn();
}
@@ -150,7 +151,7 @@ public class LockdownVpnTracker {
showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected);
try {
- clearSourceRules();
+ clearSourceRulesLocked();
mNetService.setFirewallInterfaceRule(iface, true);
mNetService.setFirewallEgressSourceRule(sourceAddr, true);
@@ -167,7 +168,13 @@ public class LockdownVpnTracker {
}
public void init() {
- Slog.d(TAG, "init()");
+ synchronized (mStateLock) {
+ initLocked();
+ }
+ }
+
+ private void initLocked() {
+ Slog.d(TAG, "initLocked()");
mVpn.setEnableNotifications(false);
@@ -188,7 +195,13 @@ public class LockdownVpnTracker {
}
public void shutdown() {
- Slog.d(TAG, "shutdown()");
+ synchronized (mStateLock) {
+ shutdownLocked();
+ }
+ }
+
+ private void shutdownLocked() {
+ Slog.d(TAG, "shutdownLocked()");
mAcceptedEgressIface = null;
mErrorCount = 0;
@@ -200,7 +213,7 @@ public class LockdownVpnTracker {
} catch (RemoteException e) {
throw new RuntimeException("Problem setting firewall rules", e);
}
- clearSourceRules();
+ clearSourceRulesLocked();
hideNotification();
mContext.unregisterReceiver(mResetReceiver);
@@ -208,15 +221,15 @@ public class LockdownVpnTracker {
}
public void reset() {
- // cycle tracker, reset error count, and trigger retry
- shutdown();
- init();
synchronized (mStateLock) {
+ // cycle tracker, reset error count, and trigger retry
+ shutdownLocked();
+ initLocked();
handleStateChangedLocked();
}
}
- private void clearSourceRules() {
+ private void clearSourceRulesLocked() {
try {
if (mAcceptedIface != null) {
mNetService.setFirewallInterfaceRule(mAcceptedIface, false);