Merge "Fires geofence if the device is already in the geofence area." into jb-mr1-dev
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index f3c6566..bcb35d5 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -28,6 +28,8 @@
import android.os.RemoteException;
import android.os.Parcelable;
import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
import android.util.Log;
import android.text.TextUtils;
@@ -42,7 +44,6 @@
import java.util.HashMap;
import java.util.Map;
-import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
/**
@@ -396,8 +397,13 @@
* (never null) if no accounts of the specified type have been added.
*/
public Account[] getAccountsByType(String type) {
+ return getAccountsByTypeAsUser(type, Process.myUserHandle());
+ }
+
+ /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
+ public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
try {
- return mService.getAccounts(type);
+ return mService.getAccountsAsUser(type, userHandle.getIdentifier());
} catch (RemoteException e) {
// won't ever happen
throw new RuntimeException(e);
@@ -1175,10 +1181,26 @@
final Activity activity,
final AccountManagerCallback<Bundle> callback,
final Handler handler) {
+ return confirmCredentialsAsUser(account, options, activity, callback, handler,
+ Process.myUserHandle());
+ }
+
+ /**
+ * @hide
+ * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
+ * but for the specified user.
+ */
+ public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
+ final Bundle options,
+ final Activity activity,
+ final AccountManagerCallback<Bundle> callback,
+ final Handler handler, UserHandle userHandle) {
if (account == null) throw new IllegalArgumentException("account is null");
+ final int userId = userHandle.getIdentifier();
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
- mService.confirmCredentials(mResponse, account, options, activity != null);
+ mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
+ userId);
}
}.start();
}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 03e0c0f..2b1a2b2 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1297,8 +1297,17 @@
}
}
- public void confirmCredentials(IAccountManagerResponse response,
- final Account account, final Bundle options, final boolean expectActivityLaunch) {
+ @Override
+ public void confirmCredentialsAsUser(IAccountManagerResponse response,
+ final Account account, final Bundle options, final boolean expectActivityLaunch,
+ int userId) {
+ // Only allow the system process to read accounts of other users
+ if (userId != UserHandle.getCallingUserId()
+ && Binder.getCallingUid() != android.os.Process.myUid()) {
+ throw new SecurityException("User " + UserHandle.getCallingUserId()
+ + " trying to confirm account credentials for " + userId);
+ }
+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "confirmCredentials: " + account
+ ", response " + response
@@ -1309,7 +1318,7 @@
if (response == null) throw new IllegalArgumentException("response is null");
if (account == null) throw new IllegalArgumentException("account is null");
checkManageAccountsPermission();
- UserAccounts accounts = getUserAccountsForCaller();
+ UserAccounts accounts = getUserAccounts(userId);
long identityToken = clearCallingIdentity();
try {
new Session(accounts, response, account.type, expectActivityLaunch,
@@ -1548,14 +1557,22 @@
return runningAccounts.toArray(accountsArray);
}
- public Account[] getAccounts(String type) {
+ @Override
+ public Account[] getAccountsAsUser(String type, int userId) {
+ // Only allow the system process to read accounts of other users
+ if (userId != UserHandle.getCallingUserId()
+ && Binder.getCallingUid() != android.os.Process.myUid()) {
+ throw new SecurityException("User " + UserHandle.getCallingUserId()
+ + " trying to get account for " + userId);
+ }
+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAccounts: accountType " + type
+ ", caller's uid " + Binder.getCallingUid()
+ ", pid " + Binder.getCallingPid());
}
checkReadAccountsPermission();
- UserAccounts accounts = getUserAccountsForCaller();
+ UserAccounts accounts = getUserAccounts(userId);
long identityToken = clearCallingIdentity();
try {
synchronized (accounts.cacheLock) {
@@ -1566,6 +1583,11 @@
}
}
+ @Override
+ public Account[] getAccounts(String type) {
+ return getAccountsAsUser(type, UserHandle.getCallingUserId());
+ }
+
public void getAccountsByFeatures(IAccountManagerResponse response,
String type, String[] features) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 6007321..dbb4924 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -31,6 +31,7 @@
String getUserData(in Account account, String key);
AuthenticatorDescription[] getAuthenticatorTypes();
Account[] getAccounts(String accountType);
+ Account[] getAccountsAsUser(String accountType, int userId);
void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features);
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
boolean addAccount(in Account account, String password, in Bundle extras);
@@ -53,8 +54,8 @@
String authTokenType, boolean expectActivityLaunch, in Bundle options);
void editProperties(in IAccountManagerResponse response, String accountType,
boolean expectActivityLaunch);
- void confirmCredentials(in IAccountManagerResponse response, in Account account,
- in Bundle options, boolean expectActivityLaunch);
+ void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account,
+ in Bundle options, boolean expectActivityLaunch, int userId);
void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
String authTokenType);
}
diff --git a/core/res/res/layout/keyguard_sim_pin_view.xml b/core/res/res/layout/keyguard_sim_pin_view.xml
index fbfb7cf..67af6f9 100644
--- a/core/res/res/layout/keyguard_sim_pin_view.xml
+++ b/core/res/res/layout/keyguard_sim_pin_view.xml
@@ -27,7 +27,7 @@
android:gravity="center_horizontal">
<ImageView
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_lockscreen_sim"/>
diff --git a/core/res/res/layout/keyguard_sim_puk_view.xml b/core/res/res/layout/keyguard_sim_puk_view.xml
index 10b86b8..b5731ec 100644
--- a/core/res/res/layout/keyguard_sim_puk_view.xml
+++ b/core/res/res/layout/keyguard_sim_puk_view.xml
@@ -28,7 +28,7 @@
android:gravity="center_horizontal">
<ImageView
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_lockscreen_sim"/>
diff --git a/core/res/res/layout/keyguard_widget_remove_drop_target.xml b/core/res/res/layout/keyguard_widget_remove_drop_target.xml
index c4fe9e0..f9f40ab 100644
--- a/core/res/res/layout/keyguard_widget_remove_drop_target.xml
+++ b/core/res/res/layout/keyguard_widget_remove_drop_target.xml
@@ -24,9 +24,10 @@
android:paddingRight="40dp"
android:drawableLeft="@drawable/kg_widget_delete_drop_target"
android:drawablePadding="4dp"
+ android:text="@string/kg_reordering_delete_drop_target_text"
android:textColor="#FFF"
android:textSize="13sp"
android:shadowColor="#000"
android:shadowDy="1.0"
android:shadowRadius="1.0"
- android:visibility="gone" />
\ No newline at end of file
+ android:visibility="gone" />
diff --git a/core/res/res/values-land/bools.xml b/core/res/res/values-land/bools.xml
index 85c64d9..a1dd2e4 100644
--- a/core/res/res/values-land/bools.xml
+++ b/core/res/res/values-land/bools.xml
@@ -16,6 +16,7 @@
<resources>
<bool name="kg_enable_camera_default_widget">false</bool>
+ <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool>
<bool name="kg_share_status_area">false</bool>
<bool name="kg_sim_puk_account_full_screen">false</bool>
</resources>
diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml
index eae4f87..00f45c1 100644
--- a/core/res/res/values-sw600dp/bools.xml
+++ b/core/res/res/values-sw600dp/bools.xml
@@ -21,4 +21,6 @@
<bool name="kg_sim_puk_account_full_screen">false</bool>
<!-- No camera for you, tablet user -->
<bool name="kg_enable_camera_default_widget">false</bool>
+ <bool name="kg_center_small_widgets_vertically">true</bool>
+ <bool name="kg_top_align_page_shrink_on_bouncer_visible">false</bool>
</resources>
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index d4ead01..457131a 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -16,6 +16,8 @@
<resources>
<bool name="kg_enable_camera_default_widget">true</bool>
+ <bool name="kg_center_small_widgets_vertically">false</bool>
+ <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool>
<bool name="action_bar_embed_tabs">true</bool>
<bool name="action_bar_embed_tabs_pre_jb">false</bool>
<bool name="split_action_bar_is_narrow">true</bool>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 3a24cc1..b8ec138 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -335,4 +335,9 @@
due to the appearance of the IME), then drop the multiuser selector. -->
<dimen name="kg_squashed_layout_threshold">600dp</dimen>
+ <!-- The height of widgets which do not support vertical resizing. This is only
+ used on tablets; on phones, this size is determined by the space left by the
+ security mode. -->
+ <dimen name="kg_small_widget_height">160dp</dimen>
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 73b9021..9932d1e 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3970,6 +3970,8 @@
<!-- Sequence of characters used to separate message strings in keyguard. Typically just em-dash
with spaces on either side. [CHAR LIMIT=3] -->
<string name="kg_text_message_separator" product="default">" \u2014 "</string>
+ <!-- The delete-widget drop target button text -->
+ <string name="kg_reordering_delete_drop_target_text">Remove</string>
<!-- Message shown in dialog when user is attempting to set the music volume above the
recommended maximum level for headphones -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dfa2b4a..cd21d80 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1215,7 +1215,9 @@
<java-symbol type="bool" name="kg_enable_camera_default_widget" />
<java-symbol type="bool" name="kg_share_status_area" />
<java-symbol type="bool" name="kg_sim_puk_account_full_screen" />
+ <java-symbol type="bool" name="kg_top_align_page_shrink_on_bouncer_visible" />
<java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
+ <java-symbol type="bool" name="kg_center_small_widgets_vertically" />
<java-symbol type="color" name="kg_multi_user_text_active" />
<java-symbol type="color" name="kg_multi_user_text_inactive" />
<java-symbol type="color" name="kg_widget_pager_gradient" />
@@ -1235,6 +1237,7 @@
<java-symbol type="dimen" name="keyguard_avatar_frame_shadow_radius" />
<java-symbol type="dimen" name="kg_edge_swipe_region_size" />
<java-symbol type="dimen" name="kg_squashed_layout_threshold" />
+ <java-symbol type="dimen" name="kg_small_widget_height" />
<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" />
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
index dbd9999..0f5817a 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
@@ -188,6 +188,16 @@
return iv;
}
+ @Override
+ public void setPivotX(float pivotX) {
+ // don't pivot me
+ }
+
+ @Override
+ public void setPivotY(float pivotY) {
+ // don't pivot me
+ }
+
public void render() {
final Throwable[] thrown = new Throwable[1];
final Bitmap[] offscreen = new Bitmap[1];
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
index 3ce61d9..d552b35 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
@@ -27,6 +27,7 @@
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.UserHandle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.LoginFilter;
@@ -175,7 +176,8 @@
Intent intent = new Intent();
intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent,
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
mCallback.reportSuccessfulUnlockAttempt();
// dismiss keyguard
@@ -220,7 +222,8 @@
* find a single best match.
*/
private Account findIntendedAccount(String username) {
- Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");
+ Account[] accounts = AccountManager.get(mContext).getAccountsByTypeAsUser("com.google",
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
// Try to figure out which account they meant if they
// typed only the username (and not the domain), or got
@@ -267,7 +270,7 @@
getProgressDialog().show();
Bundle options = new Bundle();
options.putString(AccountManager.KEY_PASSWORD, password);
- AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
+ AccountManager.get(mContext).confirmCredentialsAsUser(account, options, null /* activity */,
new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
@@ -289,7 +292,7 @@
});
}
}
- }, null /* handler */);
+ }, null /* handler */, new UserHandle(mLockPatternUtils.getCurrentUser()));
}
private Dialog getProgressDialog() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
index fabab75..51407fe 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
@@ -19,6 +19,8 @@
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.IActivityManager.WaitResult;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -112,6 +114,27 @@
}
}
+ public void launchWidgetPicker(int appWidgetId) {
+ Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
+
+ pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
+ pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+
+ Bundle options = new Bundle();
+ options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
+ pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
+ pickIntent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+ launchActivity(pickIntent, false, false, null, null);
+ }
+
/**
* Launches the said intent for the current foreground user.
*
@@ -128,7 +151,8 @@
final Handler worker,
final Runnable onStarted) {
final Context context = getContext();
- final Bundle animation = ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
+ final Bundle animation = useDefaultAnimations ? null
+ : ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
LockPatternUtils lockPatternUtils = getLockPatternUtils();
intent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
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 1f31482..b586d94 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -33,12 +33,10 @@
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.os.Bundle;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.os.UserManager;
import android.util.AttributeSet;
import android.util.Log;
@@ -162,9 +160,11 @@
mAppWidgetContainer.setViewStateManager(mViewStateManager);
mAppWidgetContainer.setLockPatternUtils(mLockPatternUtils);
+ ChallengeLayout challenge = slider != null ? slider :
+ (ChallengeLayout) findViewById(R.id.multi_pane_challenge);
+ challenge.setOnBouncerStateChangedListener(mViewStateManager);
mViewStateManager.setPagedView(mAppWidgetContainer);
- mViewStateManager.setChallengeLayout(slider != null ? slider :
- (ChallengeLayout) findViewById(R.id.multi_pane_challenge));
+ mViewStateManager.setChallengeLayout(challenge);
mSecurityViewContainer = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
mKeyguardSelectorView = (KeyguardSelectorView) findViewById(R.id.keyguard_selector_view);
mViewStateManager.setSecurityViewContainer(mSecurityViewContainer);
@@ -896,14 +896,12 @@
addWidgetButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- mCallback.setOnDismissRunnable(new Runnable() {
-
- @Override
- public void run() {
- launchPickActivityIntent();
- }
- });
- mCallback.dismiss(false);
+ int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
+ if (appWidgetId != -1) {
+ mActivityLauncher.launchWidgetPicker(appWidgetId);
+ } else {
+ Log.e(TAG, "Unable to allocate an AppWidget id in lock screen");
+ }
}
});
@@ -911,41 +909,6 @@
initializeTransportControl();
}
- private void launchPickActivityIntent() {
- // Create intent to pick widget
- Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
-
- int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
- if (appWidgetId != -1) {
- pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
- pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
- AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
-
- pickIntent.putExtra(Intent.EXTRA_INTENT, getBaseIntent());
- pickIntent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_SINGLE_TOP
- | Intent.FLAG_ACTIVITY_CLEAR_TOP
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- mContext.startActivityAsUser(pickIntent,
- new UserHandle(UserHandle.USER_CURRENT));
- } else {
- Log.e(TAG, "Unable to allocate an AppWidget id in lock screen");
- }
- }
-
- private Intent getBaseIntent() {
- Intent baseIntent = new Intent(Intent.ACTION_MAIN, null);
- baseIntent.addCategory(Intent.CATEGORY_DEFAULT);
-
- Bundle options = new Bundle();
- options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
- AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
- baseIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
- return baseIntent;
- }
-
private void removeTransportFromWidgetPager() {
int page = getWidgetPosition(R.id.keyguard_transport_control);
if (page != -1) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
index 3a82687..186d717 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -295,7 +296,8 @@
private AccountAnalyzer(AccountManager accountManager) {
mAccountManager = accountManager;
- mAccounts = accountManager.getAccountsByType("com.google");
+ mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
}
private void next() {
@@ -306,7 +308,8 @@
}
// lookup the confirmCredentials intent for the current account
- mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
+ mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
+ null, new UserHandle(mLockPatternUtils.getCurrentUser()));
}
public void start() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index 7c117d9..6d88652 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -122,6 +122,7 @@
class ViewManagerHost extends FrameLayout {
public ViewManagerHost(Context context) {
super(context);
+ setFitsSystemWindows(true);
}
@Override
@@ -164,7 +165,8 @@
mKeyguardHost = new ViewManagerHost(mContext);
- int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
+ int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
if (!mNeedsInput) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index d0fa81e..3648d99 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -881,7 +881,9 @@
* Dismiss the keyguard through the security layers.
*/
public void dismiss() {
- mKeyguardViewManager.dismiss();
+ if (mShowing && !mHidden) {
+ mKeyguardViewManager.dismiss();
+ }
}
/**
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
index 969b65e..e53358b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
@@ -19,7 +19,9 @@
import android.os.Looper;
import android.view.View;
-public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChallengeScrolledListener {
+public class KeyguardViewStateManager implements
+ SlidingChallengeLayout.OnChallengeScrolledListener,
+ ChallengeLayout.OnBouncerStateChangedListener {
private KeyguardWidgetPager mKeyguardWidgetPager;
private ChallengeLayout mChallengeLayout;
@@ -196,6 +198,7 @@
@Override
public void onScrollStateChanged(int scrollState) {
if (mKeyguardWidgetPager == null || mChallengeLayout == null) return;
+
boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
@@ -226,15 +229,24 @@
KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
if (frame == null) return;
- frame.showFrame(this);
+ // Skip showing the frame and shrinking the widget if we are
+ if (!mChallengeLayout.isBouncing()) {
+ frame.showFrame(this);
- // As soon as the security begins sliding, the widget becomes small (if it wasn't
- // small to begin with).
- if (!frame.isSmall()) {
- // We need to fetch the final page, in case the pages are in motion.
- mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
- frame.shrinkWidget();
+ // As soon as the security begins sliding, the widget becomes small (if it wasn't
+ // small to begin with).
+ if (!frame.isSmall()) {
+ // We need to fetch the final page, in case the pages are in motion.
+ mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
+ frame.shrinkWidget();
+ }
+ } else {
+ if (!frame.isSmall()) {
+ // We need to fetch the final page, in case the pages are in motion.
+ mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
+ }
}
+
// View is on the move. Pause the security view until it completes.
mKeyguardSecurityContainer.onPause();
}
@@ -279,4 +291,14 @@
public int getTransportState() {
return mTransportState;
}
+
+ // ChallengeLayout.OnBouncerStateChangedListener
+ @Override
+ public void onBouncerStateChanged(boolean bouncerActive) {
+ if (bouncerActive) {
+ mKeyguardWidgetPager.zoomOutToBouncer();
+ } else {
+ mKeyguardWidgetPager.zoomInFromBouncer();
+ }
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
index 213b82f..fa1a1ae 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
@@ -112,6 +112,10 @@
mFrameStrokeAdjustment = (int) (2 * density);
+ // This will be overriden on phones based on the current security mode, however on tablets
+ // we need to specify a height.
+ mSmallWidgetHeight =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.kg_small_widget_height);
mBackgroundDrawable = res.getDrawable(R.drawable.kg_bouncer_bg_white);
mGradientColor = res.getColor(com.android.internal.R.color.kg_widget_pager_gradient);
mGradientPaint.setXfermode(sAddBlendMode);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
index 7943b23..274e12b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -44,7 +44,7 @@
import java.util.ArrayList;
public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener,
- OnLongClickListener {
+ OnLongClickListener, ChallengeLayout.OnBouncerStateChangedListener {
ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
private static float CAMERA_DISTANCE = 10000;
@@ -64,6 +64,7 @@
private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000;
private static final String TAG = "KeyguardWidgetPager";
+ private boolean mCenterSmallWidgetsVertically;
private int mPage = 0;
private Callbacks mCallbacks;
@@ -72,6 +73,10 @@
private int mWidgetToResetAfterFadeOut;
+ // Bouncer
+ protected int BOUNCER_ZOOM_IN_OUT_DURATION = 250;
+ private float BOUNCER_SCALE_FACTOR = 0.67f;
+
// Background worker thread: used here for persistence, also made available to widget frames
private final HandlerThread mBackgroundWorkerThread;
private final Handler mBackgroundWorkerHandler;
@@ -94,6 +99,8 @@
Resources r = getResources();
mCameraWidgetEnabled = r.getBoolean(R.bool.kg_enable_camera_default_widget);
+ mCenterSmallWidgetsVertically =
+ r.getBoolean(com.android.internal.R.bool.kg_center_small_widgets_vertically);
mBackgroundWorkerThread = new HandlerThread("KeyguardWidgetPager Worker");
mBackgroundWorkerThread.start();
mBackgroundWorkerHandler = new Handler(mBackgroundWorkerThread.getLooper());
@@ -277,6 +284,9 @@
} else {
// Lock the widget to be small.
frame.setWidgetLockedSmall(true);
+ if (mCenterSmallWidgetsVertically) {
+ lp.gravity = Gravity.CENTER;
+ }
}
}
} else {
@@ -706,4 +716,46 @@
KeyguardWidgetFrame child = getWidgetPageAt(viewIndex);
child.setIsHoveringOverDeleteDropTarget(isHovering);
}
+
+ // ChallengeLayout.OnBouncerStateChangedListener
+ @Override
+ public void onBouncerStateChanged(boolean bouncerActive) {
+ if (bouncerActive) {
+ zoomOutToBouncer();
+ } else {
+ zoomInFromBouncer();
+ }
+ }
+
+ // Zoom in after the bouncer is dismissed
+ void zoomInFromBouncer() {
+ if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
+ mZoomInOutAnim.cancel();
+ }
+ final View currentPage = getPageAt(getCurrentPage());
+ if (currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f) {
+ mZoomInOutAnim = new AnimatorSet();
+ mZoomInOutAnim.setDuration(BOUNCER_ZOOM_IN_OUT_DURATION);
+ mZoomInOutAnim.playTogether(
+ ObjectAnimator.ofFloat(currentPage, "scaleX", 1f),
+ ObjectAnimator.ofFloat(currentPage , "scaleY", 1f));
+ mZoomInOutAnim.start();
+ }
+ }
+
+ // Zoom out after the bouncer is initiated
+ void zoomOutToBouncer() {
+ if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
+ mZoomInOutAnim.cancel();
+ }
+ View currentPage = getPageAt(getCurrentPage());
+ if (!(currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f)) {
+ mZoomInOutAnim = new AnimatorSet();
+ mZoomInOutAnim.setDuration(BOUNCER_ZOOM_IN_OUT_DURATION);
+ mZoomInOutAnim.playTogether(
+ ObjectAnimator.ofFloat(currentPage, "scaleX", BOUNCER_SCALE_FACTOR),
+ ObjectAnimator.ofFloat(currentPage, "scaleY", BOUNCER_SCALE_FACTOR));
+ mZoomInOutAnim.start();
+ }
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
index 00a0aed..8f47578 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
@@ -24,6 +24,7 @@
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Matrix;
@@ -209,7 +210,7 @@
private long REORDERING_DELETE_DROP_TARGET_FADE_DURATION = 150;
private float mMinScale = 1f;
protected View mDragView;
- private AnimatorSet mZoomInOutAnim;
+ protected AnimatorSet mZoomInOutAnim;
private Runnable mSidePageHoverRunnable;
private int mSidePageHoverIndex = -1;
// This variable's scope is only for the duration of startReordering() and endReordering()
@@ -246,6 +247,9 @@
// Drop to delete
private View mDeleteDropTarget;
+ // Bouncer
+ private boolean mTopAlignPageWhenShrinkingForBouncer = false;
+
public interface PageSwitchListener {
void onPageSwitching(View newPage, int newPageIndex);
void onPageSwitched(View newPage, int newPageIndex);
@@ -270,8 +274,10 @@
a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
a.recycle();
- mEdgeSwipeRegionSize =
- getResources().getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
+ Resources r = getResources();
+ mEdgeSwipeRegionSize = r.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
+ mTopAlignPageWhenShrinkingForBouncer =
+ r.getBoolean(R.bool.kg_top_align_page_shrink_on_bouncer_visible);
setHapticFeedbackEnabled(false);
init();
@@ -645,6 +651,10 @@
MeasureSpec.makeMeasureSpec(heightSize - verticalPadding, childHeightMode);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ if (mTopAlignPageWhenShrinkingForBouncer) {
+ child.setPivotX(child.getWidth() / 2);
+ child.setPivotY(0f);
+ }
}
setMeasuredDimension(scaledWidthSize, scaledHeightSize);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
index 2712494..16ec8c5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
@@ -29,6 +29,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.FloatProperty;
import android.util.Log;
import android.util.Property;
@@ -64,6 +65,8 @@
private Drawable mFrameDrawable;
private boolean mEdgeCaptured;
+ private DisplayMetrics mDisplayMetrics;
+
// Initialized during measurement from child layoutparams
private View mExpandChallengeView;
private KeyguardSecurityContainer mChallengeView;
@@ -264,7 +267,8 @@
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mTouchSlopSquare = mTouchSlop * mTouchSlop;
- final float density = res.getDisplayMetrics().density;
+ mDisplayMetrics = res.getDisplayMetrics();
+ final float density = mDisplayMetrics.density;
// top half of the lock icon, plus another 25% to be sure
mDragHandleClosedAbove = (int) (DRAG_HANDLE_CLOSED_ABOVE * density + 0.5f);
@@ -481,6 +485,14 @@
return;
}
mChallengeShowing = showChallenge;
+
+ if (mExpandChallengeView == null || mChallengeView == null) {
+ // These might not be here yet if we haven't been through layout.
+ // If we haven't, the first layout pass will set everything up correctly
+ // based on mChallengeShowing as set above.
+ return;
+ }
+
if (mChallengeShowing) {
mExpandChallengeView.setVisibility(View.INVISIBLE);
mChallengeView.setVisibility(View.VISIBLE);
@@ -520,8 +532,8 @@
@Override
public void showBouncer() {
if (mIsBouncing) return;
- showChallenge(true);
mIsBouncing = true;
+ showChallenge(true);
if (mScrimView != null) {
mScrimView.setVisibility(VISIBLE);
}
@@ -887,9 +899,27 @@
continue;
}
// Don't measure the challenge view twice!
- if (child != mChallengeView) {
- measureChildWithMargins(child, widthSpec, 0, heightSpec, 0);
+ if (child == mChallengeView) continue;
+
+ // Measure children. Widget frame measures special, so that we can ignore
+ // insets for the IME.
+ int parentWidthSpec = widthSpec, parentHeightSpec = heightSpec;
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) {
+ final View root = getRootView();
+ if (root != null) {
+ // This calculation is super dodgy and relies on several assumptions.
+ // Specifically that the root of the window will be padded in for insets
+ // and that the window is LAYOUT_IN_SCREEN.
+ final int windowWidth = mDisplayMetrics.widthPixels;
+ final int windowHeight = mDisplayMetrics.heightPixels - root.getPaddingTop();
+ parentWidthSpec = MeasureSpec.makeMeasureSpec(
+ windowWidth, MeasureSpec.EXACTLY);
+ parentHeightSpec = MeasureSpec.makeMeasureSpec(
+ windowHeight, MeasureSpec.EXACTLY);
+ }
}
+ measureChildWithMargins(child, parentWidthSpec, 0, parentHeightSpec, 0);
}
}