diff options
Diffstat (limited to 'policy')
12 files changed, 788 insertions, 285 deletions
diff --git a/policy/src/com/android/internal/policy/impl/BarController.java b/policy/src/com/android/internal/policy/impl/BarController.java index 0ce4b12..fc49a569 100644 --- a/policy/src/com/android/internal/policy/impl/BarController.java +++ b/policy/src/com/android/internal/policy/impl/BarController.java @@ -108,7 +108,7 @@ public class BarController { if (mWin != null) { if (win != null && (win.getAttrs().privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) == 0) { - if ((win.getAttrs().flags & mTranslucentWmFlag) != 0) { + if ((PolicyControl.getWindowFlags(win, null) & mTranslucentWmFlag) != 0) { vis |= mTranslucentFlag; } else { vis &= ~mTranslucentFlag; diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index b8300af..fec9dda 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -417,36 +417,38 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } private void addUsersToMenu(ArrayList<Action> items) { - List<UserInfo> users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)) - .getUsers(); - if (users.size() > 1) { + UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + if (um.isUserSwitcherEnabled()) { + List<UserInfo> users = um.getUsers(); UserInfo currentUser = getCurrentUser(); for (final UserInfo user : users) { - boolean isCurrentUser = currentUser == null - ? user.id == 0 : (currentUser.id == user.id); - Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath) - : null; - SinglePressAction switchToUser = new SinglePressAction( - com.android.internal.R.drawable.ic_menu_cc, icon, - (user.name != null ? user.name : "Primary") - + (isCurrentUser ? " \u2714" : "")) { - public void onPress() { - try { - ActivityManagerNative.getDefault().switchUser(user.id); - } catch (RemoteException re) { - Log.e(TAG, "Couldn't switch user " + re); + if (user.supportsSwitchTo()) { + boolean isCurrentUser = currentUser == null + ? user.id == 0 : (currentUser.id == user.id); + Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath) + : null; + SinglePressAction switchToUser = new SinglePressAction( + com.android.internal.R.drawable.ic_menu_cc, icon, + (user.name != null ? user.name : "Primary") + + (isCurrentUser ? " \u2714" : "")) { + public void onPress() { + try { + ActivityManagerNative.getDefault().switchUser(user.id); + } catch (RemoteException re) { + Log.e(TAG, "Couldn't switch user " + re); + } } - } - public boolean showDuringKeyguard() { - return true; - } + public boolean showDuringKeyguard() { + return true; + } - public boolean showBeforeProvisioning() { - return false; - } - }; - items.add(switchToUser); + public boolean showBeforeProvisioning() { + return false; + } + }; + items.add(switchToUser); + } } } } @@ -645,7 +647,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac icon.setImageDrawable(mIcon); icon.setScaleType(ScaleType.CENTER_CROP); } else if (mIconResId != 0) { - icon.setImageDrawable(context.getResources().getDrawable(mIconResId)); + icon.setImageDrawable(context.getDrawable(mIconResId)); } if (mMessage != null) { messageView.setText(mMessage); @@ -735,7 +737,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac boolean on = ((mState == State.On) || (mState == State.TurningOn)); if (icon != null) { - icon.setImageDrawable(context.getResources().getDrawable( + icon.setImageDrawable(context.getDrawable( (on ? mEnabledIconResId : mDisabledIconResid))); icon.setEnabled(enabled); } diff --git a/policy/src/com/android/internal/policy/impl/IconUtilities.java b/policy/src/com/android/internal/policy/impl/IconUtilities.java index a47c904..82f26ad 100644 --- a/policy/src/com/android/internal/policy/impl/IconUtilities.java +++ b/policy/src/com/android/internal/policy/impl/IconUtilities.java @@ -24,22 +24,13 @@ import android.graphics.Bitmap; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; -import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.TableMaskFilter; -import android.graphics.Typeface; -import android.text.Layout.Alignment; -import android.text.StaticLayout; -import android.text.TextPaint; import android.util.DisplayMetrics; -import android.util.Log; import android.util.TypedValue; -import android.view.ContextThemeWrapper; import android.content.res.Resources; import android.content.Context; diff --git a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java index b734c41..5602206 100644 --- a/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java +++ b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java @@ -19,6 +19,7 @@ package com.android.internal.policy.impl; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.app.ActivityManager; +import android.app.ActivityManagerNative; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -27,12 +28,12 @@ import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.os.Message; +import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; -import android.text.TextUtils; -import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.Slog; +import android.util.SparseBooleanArray; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -46,8 +47,6 @@ import android.widget.FrameLayout; import com.android.internal.R; -import java.util.Arrays; - /** * Helper to manage showing/hiding a confirmation prompt when the navigation bar is hidden * entering immersive mode. @@ -56,19 +55,19 @@ public class ImmersiveModeConfirmation { private static final String TAG = "ImmersiveModeConfirmation"; private static final boolean DEBUG = false; private static final boolean DEBUG_SHOW_EVERY_TIME = false; // super annoying, use with caution + private static final String CONFIRMED = "confirmed"; private final Context mContext; private final H mHandler; - private final ArraySet<String> mConfirmedPackages = new ArraySet<String>(); private final long mShowDelayMs; private final long mPanicThresholdMs; + private final SparseBooleanArray mUserPanicResets = new SparseBooleanArray(); + private boolean mConfirmed; private ClingWindowView mClingWindow; - private String mLastPackage; - private String mPromptPackage; private long mPanicTime; - private String mPanicPackage; private WindowManager mWindowManager; + private int mCurrentUserId; public ImmersiveModeConfirmation(Context context) { mContext = context; @@ -85,83 +84,84 @@ public class ImmersiveModeConfirmation { return exit != null ? exit.getDuration() : 0; } - public void loadSetting() { - if (DEBUG) Slog.d(TAG, "loadSetting()"); - mConfirmedPackages.clear(); - String packages = null; + public void loadSetting(int currentUserId) { + mConfirmed = false; + mCurrentUserId = currentUserId; + if (DEBUG) Slog.d(TAG, String.format("loadSetting() mCurrentUserId=%d resetForPanic=%s", + mCurrentUserId, mUserPanicResets.get(mCurrentUserId, false))); + String value = null; try { - packages = Settings.Secure.getStringForUser(mContext.getContentResolver(), + value = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS, UserHandle.USER_CURRENT); - if (packages != null) { - mConfirmedPackages.addAll(Arrays.asList(packages.split(","))); - if (DEBUG) Slog.d(TAG, "Loaded mConfirmedPackages=" + mConfirmedPackages); - } + mConfirmed = CONFIRMED.equals(value); + if (DEBUG) Slog.d(TAG, "Loaded mConfirmed=" + mConfirmed); } catch (Throwable t) { - Slog.w(TAG, "Error loading confirmations, packages=" + packages, t); + Slog.w(TAG, "Error loading confirmations, value=" + value, t); } } private void saveSetting() { if (DEBUG) Slog.d(TAG, "saveSetting()"); try { - final String packages = TextUtils.join(",", mConfirmedPackages); + final String value = mConfirmed ? CONFIRMED : null; Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS, - packages, + value, UserHandle.USER_CURRENT); - if (DEBUG) Slog.d(TAG, "Saved packages=" + packages); + if (DEBUG) Slog.d(TAG, "Saved value=" + value); } catch (Throwable t) { - Slog.w(TAG, "Error saving confirmations, mConfirmedPackages=" + mConfirmedPackages, t); + Slog.w(TAG, "Error saving confirmations, mConfirmed=" + mConfirmed, t); } } public void immersiveModeChanged(String pkg, boolean isImmersiveMode) { - if (pkg == null) { - return; - } mHandler.removeMessages(H.SHOW); if (isImmersiveMode) { - mLastPackage = pkg; - if (DEBUG_SHOW_EVERY_TIME || !mConfirmedPackages.contains(pkg)) { - mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs); + final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg); + if (DEBUG) Slog.d(TAG, String.format("immersiveModeChanged() disabled=%s mConfirmed=%s", + disabled, mConfirmed)); + if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed)) { + mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs); } } else { - mLastPackage = null; mHandler.sendEmptyMessage(H.HIDE); } } - public void onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) { - if (mPanicPackage != null && !isScreenOn && (time - mPanicTime < mPanicThresholdMs)) { + public boolean onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) { + if (!isScreenOn && (time - mPanicTime < mPanicThresholdMs)) { // turning the screen back on within the panic threshold - unconfirmPackage(mPanicPackage); + mHandler.sendEmptyMessage(H.PANIC); + return mClingWindow == null; } if (isScreenOn && inImmersiveMode) { // turning the screen off, remember if we were in immersive mode mPanicTime = time; - mPanicPackage = mLastPackage; } else { mPanicTime = 0; - mPanicPackage = null; } + return false; } public void confirmCurrentPrompt() { - mHandler.post(confirmAction(mPromptPackage)); + if (mClingWindow != null) { + if (DEBUG) Slog.d(TAG, "confirmCurrentPrompt()"); + mHandler.post(mConfirm); + } } - private void unconfirmPackage(String pkg) { - if (pkg != null) { - if (DEBUG) Slog.d(TAG, "Unconfirming immersive mode confirmation for " + pkg); - mConfirmedPackages.remove(pkg); - saveSetting(); - } + private void handlePanic() { + if (DEBUG) Slog.d(TAG, "handlePanic()"); + if (mUserPanicResets.get(mCurrentUserId, false)) return; // already reset for panic + mUserPanicResets.put(mCurrentUserId, true); + mConfirmed = false; + saveSetting(); } private void handleHide() { if (mClingWindow != null) { - if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation for " + mPromptPackage); + if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation"); mWindowManager.removeView(mClingWindow); mClingWindow = null; } @@ -297,11 +297,10 @@ public class ImmersiveModeConfirmation { } } - private void handleShow(String pkg) { - mPromptPackage = pkg; - if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation for " + pkg); + private void handleShow() { + if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation"); - mClingWindow = new ClingWindowView(mContext, confirmAction(pkg)); + mClingWindow = new ClingWindowView(mContext, mConfirm); // we will be hiding the nav bar, so layout as if it's already hidden mClingWindow.setSystemUiVisibility( @@ -313,33 +312,35 @@ public class ImmersiveModeConfirmation { mWindowManager.addView(mClingWindow, lp); } - private Runnable confirmAction(final String pkg) { - return new Runnable() { - @Override - public void run() { - if (pkg != null && !mConfirmedPackages.contains(pkg)) { - if (DEBUG) Slog.d(TAG, "Confirming immersive mode for " + pkg); - mConfirmedPackages.add(pkg); - saveSetting(); - } - handleHide(); + private final Runnable mConfirm = new Runnable() { + @Override + public void run() { + if (DEBUG) Slog.d(TAG, "mConfirm.run()"); + if (!mConfirmed) { + mConfirmed = true; + saveSetting(); } - }; - } + handleHide(); + } + }; private final class H extends Handler { - private static final int SHOW = 0; - private static final int HIDE = 1; + private static final int SHOW = 1; + private static final int HIDE = 2; + private static final int PANIC = 3; @Override public void handleMessage(Message msg) { switch(msg.what) { case SHOW: - handleShow((String)msg.obj); + handleShow(); break; case HIDE: handleHide(); break; + case PANIC: + handlePanic(); + break; } } } diff --git a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java index 968976b..df6fca4c 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java +++ b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java @@ -16,8 +16,6 @@ package com.android.internal.policy.impl; -import java.util.Map; - import android.content.Context; import android.util.AttributeSet; import android.view.View; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 78020e9..b1fea03 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -22,8 +22,6 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowManager.LayoutParams.*; -import android.view.ViewConfiguration; - import com.android.internal.R; import com.android.internal.view.RootViewSurfaceTaker; import com.android.internal.view.StandaloneActionMode; @@ -40,6 +38,9 @@ import com.android.internal.widget.ActionBarOverlayLayout; import com.android.internal.widget.ActionBarView; import com.android.internal.widget.SwipeDismissLayout; +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.app.ActivityOptions; import android.app.KeyguardManager; import android.content.Context; import android.content.pm.ActivityInfo; @@ -53,17 +54,26 @@ import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.net.Uri; import android.os.Bundle; -import android.os.Debug; import android.os.Handler; +import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; +import android.transition.ChangeBounds; +import android.transition.Explode; +import android.transition.Fade; +import android.transition.MoveImage; +import android.transition.Scene; +import android.transition.Transition; +import android.transition.TransitionInflater; +import android.transition.TransitionManager; +import android.transition.TransitionSet; import android.util.AndroidRuntimeException; +import android.util.ArrayMap; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; -import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; import android.view.ActionMode; @@ -81,11 +91,13 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewManager; import android.view.ViewParent; import android.view.ViewRootImpl; import android.view.ViewStub; +import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; @@ -100,6 +112,8 @@ import android.widget.TextView; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; /** * Android-specific Window. @@ -112,7 +126,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private final static String TAG = "PhoneWindow"; private final static boolean SWEEP_OPEN_MENU = false; - /** * Simple callback used by the context menu and its submenus. The options * menu submenus do not use this (their behavior is more complex). @@ -135,19 +148,22 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private ViewGroup mContentParent; SurfaceHolder.Callback2 mTakeSurfaceCallback; - + InputQueue.Callback mTakeInputQueueCallback; - + private boolean mIsFloating; private LayoutInflater mLayoutInflater; private TextView mTitleView; - + private ActionBarView mActionBar; private ActionMenuPresenterCallback mActionMenuPresenterCallback; private PanelMenuPresenterCallback mPanelMenuPresenterCallback; + private TransitionManager mTransitionManager; + private Scene mContentScene; + // The icon resource has been explicitly set elsewhere // and should not be overwritten with a default. static final int FLAG_RESOURCE_SET_ICON = 1 << 0; @@ -228,6 +244,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } }; + private Transition mEnterTransition; + private Transition mExitTransition; + private Transition mSharedElementEnterTransition; + private Transition mSharedElementExitTransition; + private Boolean mAllowExitTransitionOverlap; + private Boolean mAllowEnterTransitionOverlap; + static class WindowManagerHolder { static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService("window")); @@ -292,13 +315,38 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override + public TransitionManager getTransitionManager() { + return mTransitionManager; + } + + @Override + public void setTransitionManager(TransitionManager tm) { + mTransitionManager = tm; + } + + @Override + public Scene getContentScene() { + return mContentScene; + } + + @Override public void setContentView(int layoutResID) { + // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window + // decor, when theme attributes and the like are crystalized. Do not check the feature + // before this happens. if (mContentParent == null) { installDecor(); - } else { + } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } - mLayoutInflater.inflate(layoutResID, mContentParent); + + if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { + final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, + getContext()); + transitionTo(newScene); + } else { + mLayoutInflater.inflate(layoutResID, mContentParent); + } final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); @@ -312,12 +360,22 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { @Override public void setContentView(View view, ViewGroup.LayoutParams params) { + // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window + // decor, when theme attributes and the like are crystalized. Do not check the feature + // before this happens. if (mContentParent == null) { installDecor(); - } else { + } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } - mContentParent.addView(view, params); + + if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { + view.setLayoutParams(params); + final Scene newScene = new Scene(mContentParent, view); + transitionTo(newScene); + } else { + mContentParent.addView(view, params); + } final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); @@ -329,6 +387,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mContentParent == null) { installDecor(); } + if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { + // TODO Augment the scenes/transitions API to support this. + throw new UnsupportedOperationException( + "addContentView does not support content transitions"); + } mContentParent.addView(view, params); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { @@ -336,6 +399,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } + private void transitionTo(Scene scene) { + if (mContentScene == null) { + scene.enter(); + } else { + mTransitionManager.transitionTo(scene); + } + mContentScene = scene; + } + @Override public View getCurrentFocus() { return mDecor != null ? mDecor.findFocus() : null; @@ -345,11 +417,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { public void takeSurface(SurfaceHolder.Callback2 callback) { mTakeSurfaceCallback = callback; } - + public void takeInputQueue(InputQueue.Callback callback) { mTakeInputQueueCallback = callback; } - + @Override public boolean isFloating() { return mIsFloating; @@ -377,6 +449,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override + @Deprecated public void setTitleColor(int textColor) { if (mTitleView != null) { mTitleView.setTextColor(textColor); @@ -635,7 +708,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { // Otherwise, set the normal panel background backgroundResId = st.background; } - st.decorView.setWindowBackground(getContext().getResources().getDrawable( + st.decorView.setWindowBackground(getContext().getDrawable( backgroundResId)); ViewParent shownPanelParent = st.shownPanelView.getParent(); @@ -1220,7 +1293,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (st.resid != resId) { st.resid = resId; st.uri = null; - st.local = getContext().getResources().getDrawable(resId); + st.local = getContext().getDrawable(resId); updateDrawable(featureId, st, false); } } else { @@ -2236,7 +2309,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mMenuBackground == null && mFeatureId < 0 && getAttributes().height == WindowManager.LayoutParams.MATCH_PARENT) { - mMenuBackground = getContext().getResources().getDrawable( + mMenuBackground = getContext().getDrawable( com.android.internal.R.drawable.menu_background); } if (mMenuBackground != null) { @@ -2513,6 +2586,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return super.fitSystemWindows(insets); } + @Override + public boolean isTransitionGroup() { + return false; + } + private void updateStatusGuard(Rect insets) { boolean showStatusGuard = false; // Show the status guard when the non-overlay contextual action bar is showing @@ -2913,6 +2991,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { a.getValue(com.android.internal.R.styleable.Window_windowFixedHeightMinor, mFixedHeightMinor); } + if (a.getBoolean(com.android.internal.R.styleable.Window_windowContentTransitions, false)) { + requestFeature(FEATURE_CONTENT_TRANSITIONS); + } if (a.hasValue(com.android.internal.R.styleable.Window_windowOutsetBottom)) { if (mOutsetBottom == null) mOutsetBottom = new TypedValue(); a.getValue(com.android.internal.R.styleable.Window_windowOutsetBottom, mOutsetBottom); @@ -3072,12 +3153,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (getContainer() == null) { Drawable drawable = mBackgroundDrawable; if (mBackgroundResource != 0) { - drawable = getContext().getResources().getDrawable(mBackgroundResource); + drawable = getContext().getDrawable(mBackgroundResource); } mDecor.setWindowBackground(drawable); drawable = null; if (mFrameResource != 0) { - drawable = getContext().getResources().getDrawable(mFrameResource); + drawable = getContext().getDrawable(mFrameResource); } mDecor.setWindowFrame(drawable); @@ -3212,13 +3293,63 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { }); } } + + // Only inflate or create a new TransitionManager if the caller hasn't + // already set a custom one. + if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { + if (mTransitionManager == null) { + final int transitionRes = getWindowStyle().getResourceId( + com.android.internal.R.styleable.Window_windowContentTransitionManager, + 0); + if (transitionRes != 0) { + final TransitionInflater inflater = TransitionInflater.from(getContext()); + mTransitionManager = inflater.inflateTransitionManager(transitionRes, + mContentParent); + } else { + mTransitionManager = new TransitionManager(); + } + } + + mEnterTransition = getTransition(mEnterTransition, + com.android.internal.R.styleable.Window_windowEnterTransition); + mExitTransition = getTransition(mExitTransition, + com.android.internal.R.styleable.Window_windowExitTransition); + mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, + com.android.internal.R.styleable.Window_windowSharedElementEnterTransition); + mSharedElementExitTransition = getTransition(mSharedElementExitTransition, + com.android.internal.R.styleable.Window_windowSharedElementExitTransition); + if (mAllowEnterTransitionOverlap == null) { + mAllowEnterTransitionOverlap = getWindowStyle().getBoolean( + com.android.internal.R.styleable. + Window_windowAllowEnterTransitionOverlap, true); + } + if (mAllowExitTransitionOverlap == null) { + mAllowExitTransitionOverlap = getWindowStyle().getBoolean( + com.android.internal.R.styleable. + Window_windowAllowExitTransitionOverlap, true); + } + } + } + } + + private Transition getTransition(Transition currentValue, int id) { + if (currentValue != null) { + return currentValue; + } + int transitionId = getWindowStyle().getResourceId(id, -1); + Transition transition = null; + if (transitionId != -1 && transitionId != com.android.internal.R.transition.no_transition) { + TransitionInflater inflater = TransitionInflater.from(getContext()); + transition = inflater.inflateTransition(transitionId); } + return transition; } private Drawable loadImageURI(Uri uri) { try { - return Drawable.createFromStream( - getContext().getContentResolver().openInputStream(uri), null); + final Context context = getContext(); + return Drawable.createFromStreamThemed( + context.getContentResolver().openInputStream(uri), null, context.getTheme()); } catch (Exception e) { Log.w(TAG, "Unable to open content: " + uri); } @@ -3530,6 +3661,72 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return mVolumeControlStreamType; } + private boolean isTranslucent() { + TypedArray a = getWindowStyle(); + return a.getBoolean(a.getResourceId( + com.android.internal.R.styleable.Window_windowIsTranslucent, 0), false); + } + + @Override + public void setEnterTransition(Transition enterTransition) { + mEnterTransition = enterTransition; + } + + @Override + public void setExitTransition(Transition exitTransition) { + mExitTransition = exitTransition; + } + + @Override + public void setSharedElementEnterTransition(Transition sharedElementEnterTransition) { + mSharedElementEnterTransition = sharedElementEnterTransition; + } + + @Override + public void setSharedElementExitTransition(Transition sharedElementExitTransition) { + mSharedElementExitTransition = sharedElementExitTransition; + } + + @Override + public Transition getEnterTransition() { + return mEnterTransition; + } + + @Override + public Transition getExitTransition() { + return mExitTransition; + } + + @Override + public Transition getSharedElementEnterTransition() { + return mSharedElementEnterTransition; + } + + @Override + public Transition getSharedElementExitTransition() { + return mSharedElementExitTransition; + } + + @Override + public void setAllowEnterTransitionOverlap(boolean allow) { + mAllowEnterTransitionOverlap = allow; + } + + @Override + public boolean getAllowEnterTransitionOverlap() { + return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap; + } + + @Override + public void setAllowExitTransitionOverlap(boolean allowExitTransitionOverlap) { + mAllowExitTransitionOverlap = allowExitTransitionOverlap; + } + + @Override + public boolean getAllowExitTransitionOverlap() { + return (mAllowExitTransitionOverlap == null) ? true : mAllowExitTransitionOverlap; + } + private static final class DrawableFeatureState { DrawableFeatureState(int _featureId) { featureId = _featureId; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 72f1e4f..ae6aeee 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -91,10 +91,13 @@ import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import com.android.internal.R; +import com.android.internal.policy.IKeyguardService; +import com.android.internal.policy.IKeyguardServiceConstants; import com.android.internal.policy.PolicyManager; import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate; import com.android.internal.statusbar.IStatusBarService; @@ -173,6 +176,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { * Keyguard stuff */ private WindowState mKeyguardScrim; + private boolean mKeyguardHidden; + private boolean mKeyguardDrawn; /* Table of Application Launch keys. Maps from key codes to intent categories. * @@ -213,6 +218,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final Object mServiceAquireLock = new Object(); Vibrator mVibrator; // Vibrator for giving feedback of orientation changes SearchManager mSearchManager; + AccessibilityManager mAccessibilityManager; // Vibrator pattern for haptic feedback of a long press. long[] mLongPressVibePattern; @@ -223,6 +229,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Vibrator pattern for a short vibration. long[] mKeyboardTapVibePattern; + // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock. + long[] mClockTickVibePattern; + // Vibrator pattern for haptic feedback during boot when safe mode is disabled. long[] mSafeModeDisabledVibePattern; @@ -243,7 +252,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int[] mNavigationBarHeightForRotation = new int[4]; int[] mNavigationBarWidthForRotation = new int[4]; - WindowState mKeyguard = null; KeyguardServiceDelegate mKeyguardDelegate; GlobalActions mGlobalActions; volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread @@ -297,7 +305,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mOrientationSensorEnabled = false; int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; boolean mHasSoftInput = false; - boolean mTouchExplorationEnabled = false; boolean mTranslucentDecorEnabled = true; int mPointerLocationMode = 0; // guarded by mLock @@ -306,17 +313,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowState mFocusedWindow; IApplicationToken mFocusedApp; - private final class PointerLocationPointerEventListener implements PointerEventListener { - @Override - public void onPointerEvent(MotionEvent motionEvent) { - if (mPointerLocationView != null) { - mPointerLocationView.addPointerEvent(motionEvent); - } - } - } - - // Pointer location view state, only modified on the mHandler Looper. - PointerLocationPointerEventListener mPointerLocationPointerEventListener; PointerLocationView mPointerLocationView; // The current size of the screen; really; extends into the overscan area of @@ -534,9 +530,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.DEFAULT_INPUT_METHOD), false, this, UserHandle.USER_ALL); - resolver.registerContentObserver(Settings.System.getUriFor( + resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Global.getUriFor( + Settings.Global.POLICY_CONTROL), false, this, + UserHandle.USER_ALL); updateSettings(); } @@ -912,6 +911,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.bool.config_enableTranslucentDecor); readConfigurationDependentBehaviors(); + mAccessibilityManager = (AccessibilityManager) context.getSystemService( + Context.ACCESSIBILITY_SERVICE); + // register for dock events IntentFilter filter = new IntentFilter(); filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE); @@ -972,6 +974,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.array.config_virtualKeyVibePattern); mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_keyboardTapVibePattern); + mClockTickVibePattern = getLongIntArray(mContext.getResources(), + com.android.internal.R.array.config_clockTickVibePattern); mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_safeModeDisabledVibePattern); mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), @@ -986,7 +990,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { initializeHdmiState(); // Match current screen state. - if (mPowerManager.isScreenOn()) { + if (mPowerManager.isInteractive()) { wakingUp(null); } else { goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER); @@ -1110,7 +1114,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { * navigation bar and touch exploration is not enabled */ private boolean canHideNavigationBar() { - return mHasNavigationBar && !mTouchExplorationEnabled; + return mHasNavigationBar + && !mAccessibilityManager.isTouchExplorationEnabled(); } @Override @@ -1179,8 +1184,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateRotation = true; } if (mImmersiveModeConfirmation != null) { - mImmersiveModeConfirmation.loadSetting(); + mImmersiveModeConfirmation.loadSetting(mCurrentUserId); } + PolicyControl.reloadFromSetting(mContext); } if (updateRotation) { updateRotation(true); @@ -1191,7 +1197,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mPointerLocationView == null) { mPointerLocationView = new PointerLocationView(mContext); mPointerLocationView.setPrintCoords(false); - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); @@ -1211,22 +1216,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContext.getSystemService(Context.WINDOW_SERVICE); lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; wm.addView(mPointerLocationView, lp); - - mPointerLocationPointerEventListener = new PointerLocationPointerEventListener(); - mWindowManagerFuncs.registerPointerEventListener(mPointerLocationPointerEventListener); + mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView); } } private void disablePointerLocation() { - if (mPointerLocationPointerEventListener != null) { - mWindowManagerFuncs.unregisterPointerEventListener( - mPointerLocationPointerEventListener); - mPointerLocationPointerEventListener = null; - } - if (mPointerLocationView != null) { - WindowManager wm = (WindowManager) - mContext.getSystemService(Context.WINDOW_SERVICE); + mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView); + WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); wm.removeView(mPointerLocationView); mPointerLocationView = null; } @@ -1318,7 +1315,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_BOOT_PROGRESS: case TYPE_DISPLAY_OVERLAY: case TYPE_HIDDEN_NAV_CONSUMER: - case TYPE_KEYGUARD: case TYPE_KEYGUARD_SCRIM: case TYPE_KEYGUARD_DIALOG: case TYPE_MAGNIFICATION_OVERLAY: @@ -1355,6 +1351,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; break; + case TYPE_STATUS_BAR: + + // If the Keyguard is in a hidden state (occluded by another window), we force to + // remove the wallpaper and keyguard flag so that any change in-flight after setting + // the keyguard as occluded wouldn't set these flags again. + // See {@link #processKeyguardSetHiddenResultLw}. + if (mKeyguardHidden) { + attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; + attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; + } + break; + } + + if (attrs.type != TYPE_STATUS_BAR) { + // The status bar is the only window allowed to exhibit keyguard behavior. + attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; } } @@ -1441,54 +1453,50 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_KEYGUARD_SCRIM: // the safety window that shows behind keyguard while keyguard is starting return 12; - case TYPE_KEYGUARD: - // the keyguard; nothing on top of these can take focus, since they are - // responsible for power management when displayed. + case TYPE_STATUS_BAR_SUB_PANEL: return 13; - case TYPE_KEYGUARD_DIALOG: + case TYPE_STATUS_BAR: return 14; - case TYPE_STATUS_BAR_SUB_PANEL: + case TYPE_STATUS_BAR_PANEL: return 15; - case TYPE_STATUS_BAR: + case TYPE_KEYGUARD_DIALOG: return 16; - case TYPE_STATUS_BAR_PANEL: - return 17; case TYPE_VOLUME_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume - return 18; + return 17; case TYPE_SYSTEM_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume - return 19; + return 18; case TYPE_NAVIGATION_BAR: // the navigation bar, if available, shows atop most things - return 20; + return 19; case TYPE_NAVIGATION_BAR_PANEL: // some panels (e.g. search) need to show on top of the navigation bar - return 21; + return 20; case TYPE_SYSTEM_ERROR: // system-level error dialogs - return 22; + return 21; case TYPE_MAGNIFICATION_OVERLAY: // used to highlight the magnified portion of a display - return 23; + return 22; case TYPE_DISPLAY_OVERLAY: // used to simulate secondary display devices - return 24; + return 23; case TYPE_DRAG: // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows - return 25; + return 24; case TYPE_SECURE_SYSTEM_OVERLAY: - return 26; + return 25; case TYPE_BOOT_PROGRESS: - return 27; + return 26; case TYPE_POINTER: // the (mouse) pointer layer - return 28; + return 27; case TYPE_HIDDEN_NAV_CONSUMER: - return 29; + return 28; } Log.e(TAG, "Unknown window type: " + type); return 2; @@ -1558,7 +1566,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) { - return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD; + return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; } @Override @@ -1569,7 +1577,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_WALLPAPER: case TYPE_DREAM: case TYPE_UNIVERSE_BACKGROUND: - case TYPE_KEYGUARD: case TYPE_KEYGUARD_SCRIM: return false; default: @@ -1768,12 +1775,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { android.Manifest.permission.STATUS_BAR_SERVICE, "PhoneWindowManager"); break; - case TYPE_KEYGUARD: - if (mKeyguard != null) { - return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; - } - mKeyguard = win; - break; case TYPE_KEYGUARD_SCRIM: if (mKeyguardScrim != null) { return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; @@ -1790,9 +1791,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBar == win) { mStatusBar = null; mStatusBarController.setWindow(null); - } else if (mKeyguard == win) { - Log.v(TAG, "Removing keyguard window (Did it crash?)"); - mKeyguard = null; mKeyguardDelegate.showScrim(); } else if (mKeyguardScrim == win) { Log.v(TAG, "Removing keyguard scrim"); @@ -1811,12 +1809,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win + ": transit=" + transit); if (win == mStatusBar) { + boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) { - return R.anim.dock_top_exit; + return isKeyguard ? -1 : R.anim.dock_top_exit; } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { - return R.anim.dock_top_enter; + return isKeyguard ? -1 : R.anim.dock_top_enter; } } else if (win == mNavigationBar) { // This can be on either the bottom or the right. @@ -2037,9 +2036,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; if (attrs != null) { final int type = attrs.type; - if (type == WindowManager.LayoutParams.TYPE_KEYGUARD - || type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM - || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { + if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM + || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG + || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { // the "app" is keyguard, so give it the key return 0; } @@ -2468,7 +2467,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { * given the situation with the keyguard. */ void launchHomeFromHotKey() { - if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotHidden()) { + if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotOccluded()) { // don't launch home if keyguard showing } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) { // when in keyguard restricted mode, must first verify unlock @@ -2588,8 +2587,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) { - final int fl = attrs.flags; - final int systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); + final int fl = PolicyControl.getWindowFlags(null, attrs); + final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs); + final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility); if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { @@ -2761,7 +2761,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // We currently want to hide the navigation UI. mNavigationBarController.setBarShowingLw(false); } - if (navVisible && !navTranslucent && !mNavigationBar.isAnimatingLw() + if (navVisible && !navTranslucent && !navAllowedHidden + && !mNavigationBar.isAnimatingLw() && !mNavigationBarController.wasRecentlyTranslucent()) { // If the opaque nav bar is currently requested to be visible, // and not in the process of animating on or off, then @@ -2970,9 +2971,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { offsetInputMethodWindowLw(mLastInputMethodWindow); } - final int fl = attrs.flags; + final int fl = PolicyControl.getWindowFlags(win, attrs); final int sim = attrs.softInputMode; - final int sysUiFl = win.getSystemUiVisibility(); + final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null); final Rect pf = mTmpParentFrame; final Rect df = mTmpDisplayFrame; @@ -3088,9 +3089,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { + mOverscanScreenHeight; } else if (canHideNavigationBar() && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 - && (attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD || ( - attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW - && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { + && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { // Asking for layout as if the nav bar is hidden, lets the // application extend into the unrestricted overscan screen area. We // only do this for application windows to ensure no window that @@ -3391,21 +3391,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManager.LayoutParams attrs) { if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw=" + win.isVisibleOrBehindKeyguardLw()); + final int fl = PolicyControl.getWindowFlags(win, attrs); if (mTopFullscreenOpaqueWindowState == null && win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) { mForcingShowNavBar = true; mForcingShowNavBarLayer = win.getSurfaceLayer(); } + if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { + mForceStatusBarFromKeyguard = true; + } if (mTopFullscreenOpaqueWindowState == null && win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) { - if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) { - if (attrs.type == TYPE_KEYGUARD) { + if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { + if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { mForceStatusBarFromKeyguard = true; } else { mForceStatusBar = true; } } - if (attrs.type == TYPE_KEYGUARD) { + if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { mShowingLockscreen = true; } boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW @@ -3420,8 +3424,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - final boolean showWhenLocked = (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0; - final boolean dismissKeyguard = (attrs.flags & FLAG_DISMISS_KEYGUARD) != 0; + final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0; + final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0; if (appWindow) { if (showWhenLocked || (dismissKeyguard && !isKeyguardSecure())) { mAppsToBeHidden.remove(win.getAppToken()); @@ -3441,14 +3445,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { mForceStatusBarFromKeyguard = false; } if (dismissKeyguard && mDismissKeyguard == DISMISS_KEYGUARD_NONE) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win); + if (DEBUG_LAYOUT) Slog.v(TAG, + "Setting mDismissKeyguard true by win " + win); mDismissKeyguard = mWinDismissingKeyguard == win ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; mWinDismissingKeyguard = win; mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure(); } } - if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { + if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { mAllowLockscreenWhenOn = true; } } @@ -3491,13 +3496,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { mLastSystemUiFlags, mLastSystemUiFlags); } } else if (mTopFullscreenOpaqueWindowState != null) { + final int fl = PolicyControl.getWindowFlags(null, lp); if (localLOGV) { Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() - + " lp.flags=0x" + Integer.toHexString(lp.flags)); + + " lp.flags=0x" + Integer.toHexString(fl)); } - topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 + topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; // The subtle difference between the window for mTopFullscreenOpaqueWindowState // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window @@ -3533,11 +3539,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Hide the key guard if a visible window explicitly specifies that it wants to be // displayed when the screen is locked. - if (mKeyguard != null) { + if (mKeyguardDelegate != null && mStatusBar != null) { if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard=" + mHideLockScreen); if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) { - if (mKeyguard.hideLw(true)) { + mKeyguardHidden = true; + if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) { changes |= FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG | FINISH_LAYOUT_REDO_WALLPAPER; @@ -3551,24 +3558,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { }); } } else if (mHideLockScreen) { - if (mKeyguard.hideLw(true)) { + mKeyguardHidden = true; + if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) { changes |= FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG | FINISH_LAYOUT_REDO_WALLPAPER; } - if (!mShowingDream) { - mKeyguardDelegate.setHidden(true); - } } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) { // This is the case of keyguard isSecure() and not mHideLockScreen. if (mDismissKeyguard == DISMISS_KEYGUARD_START) { // Only launch the next keyguard unlock window once per window. - if (mKeyguard.showLw(true)) { + mKeyguardHidden = false; + if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) { changes |= FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG | FINISH_LAYOUT_REDO_WALLPAPER; } - mKeyguardDelegate.setHidden(false); mHandler.post(new Runnable() { @Override public void run() { @@ -3578,12 +3583,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } else { mWinDismissingKeyguard = null; - if (mKeyguard.showLw(true)) { + mKeyguardHidden = false; + if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) { changes |= FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG | FINISH_LAYOUT_REDO_WALLPAPER; } - mKeyguardDelegate.setHidden(false); } } @@ -3598,9 +3603,39 @@ public class PhoneWindowManager implements WindowManagerPolicy { return changes; } + /** + * Processes the result code of {@link IKeyguardService#setOccluded}. This is needed because we + * immediately need to put the wallpaper directly behind the Keyguard when a window with flag + * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} gets dismissed. If we + * would wait for Keyguard to change the flags, that would be running asynchronously and thus be + * too late so the user might see the window behind. + * + * @param setHiddenResult The result code from {@link IKeyguardService#setOccluded}. + * @return Whether the flags have changed and we have to redo the layout. + */ + private boolean processKeyguardSetHiddenResultLw(int setHiddenResult) { + if (setHiddenResult + == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS) { + mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; + mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; + return true; + } else if (setHiddenResult + == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS) { + mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; + mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; + return true; + } else { + return false; + } + } + + private boolean isStatusBarKeyguard() { + return mStatusBar != null + && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; + } + public boolean allowAppAnimationsLw() { - if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw() - || mShowingDream) { + if (isStatusBarKeyguard() || mShowingDream) { // If keyguard or dreams is currently visible, no reason to animate behind it. return false; } @@ -3822,15 +3857,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // when the keyguard is hidden by another activity. final boolean keyguardActive = (mKeyguardDelegate == null ? false : (interactive ? - mKeyguardDelegate.isShowingAndNotHidden() : + mKeyguardDelegate.isShowingAndNotOccluded() : mKeyguardDelegate.isShowing())); - if (keyCode == KeyEvent.KEYCODE_POWER - || keyCode == KeyEvent.KEYCODE_SLEEP - || keyCode == KeyEvent.KEYCODE_WAKEUP) { - policyFlags |= WindowManagerPolicy.FLAG_WAKE; - } - if (DEBUG_INPUT) { Log.d(TAG, "interceptKeyTq keycode=" + keyCode + " interactive=" + interactive + " keyguardActive=" + keyguardActive @@ -3844,8 +3873,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Basic policy based on interactive state. int result; - boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE - | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; + boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 + || event.isWakeKey(); if (interactive || (isInjected && !isWakeKey)) { // When the screen is on or if the key is injected pass the key to the application. result = ACTION_PASS_TO_USER; @@ -3975,8 +4004,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_POWER: { result &= ~ACTION_PASS_TO_USER; if (down) { - mImmersiveModeConfirmation.onPowerKeyDown(interactive, event.getDownTime(), - isImmersiveMode(mLastSystemUiFlags)); + boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive, + event.getDownTime(), isImmersiveMode(mLastSystemUiFlags)); + if (panic) { + mHandler.post(mRequestTransientNav); + } if (interactive && !mPowerKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { mPowerKeyTriggered = true; @@ -3994,7 +4026,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { telephonyService.silenceRinger(); } else if ((mIncallPowerBehavior & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 - && telephonyService.isOffhook() && isScreenOn) { + && telephonyService.isOffhook() && interactive) { // Otherwise, if "Power button ends call" is enabled, // the Power button will hang up any current active call. hungUp = telephonyService.endCall(); @@ -4257,6 +4289,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + private final Runnable mRequestTransientNav = new Runnable() { + @Override + public void run() { + requestTransientBars(mNavigationBar); + } + }; + private void requestTransientBars(WindowState swipeTarget) { synchronized (mWindowManagerFuncs.getWindowManagerLock()) { boolean sb = mStatusBarController.checkShowTransientBarLw(); @@ -4311,21 +4350,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void waitForKeyguard(final ScreenOnListener screenOnListener) { if (mKeyguardDelegate != null) { - if (screenOnListener != null) { - mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() { - @Override - public void onShown(IBinder windowToken) { - waitForKeyguardWindowDrawn(windowToken, screenOnListener); - } - }); - return; - } else { - mKeyguardDelegate.onScreenTurnedOn(null); - } + mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() { + @Override + public void onShown(IBinder windowToken) { + waitForKeyguardWindowDrawn(windowToken, screenOnListener); + } + }); } else { Slog.i(TAG, "No keyguard interface!"); + finishScreenTurningOn(screenOnListener); } - finishScreenTurningOn(screenOnListener); } private void waitForKeyguardWindowDrawn(IBinder windowToken, @@ -4338,6 +4372,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void sendResult(Bundle data) { Slog.i(TAG, "Lock screen displayed!"); finishScreenTurningOn(screenOnListener); + setKeyguardDrawn(); } })) { return; @@ -4351,6 +4386,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Slog.i(TAG, "No lock screen! windowToken=" + windowToken); finishScreenTurningOn(screenOnListener); + setKeyguardDrawn(); } private void finishScreenTurningOn(ScreenOnListener screenOnListener) { @@ -4394,7 +4430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean keyguardIsShowingTq() { if (mKeyguardDelegate == null) return false; - return mKeyguardDelegate.isShowingAndNotHidden(); + return mKeyguardDelegate.isShowingAndNotOccluded(); } @@ -4431,6 +4467,23 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void setKeyguardDrawn() { + synchronized (mLock) { + mKeyguardDrawn = true; + } + try { + mWindowManager.enableScreenIfNeeded(); + } catch (RemoteException unhandled) { + } + } + + @Override + public boolean isKeyguardDrawnLw() { + synchronized (mLock) { + return mKeyguardDrawn; + } + } + void sendCloseSystemWindows() { sendCloseSystemWindows(mContext, null); } @@ -4714,6 +4767,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { synchronized (mLock) { mSystemBooted = true; } + waitForKeyguard(null); } ProgressDialog mBootMsgDialog = null; @@ -5042,7 +5096,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; - if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotHidden())) { + if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotOccluded())) { return false; } long[] pattern = null; @@ -5056,6 +5110,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case HapticFeedbackConstants.KEYBOARD_TAP: pattern = mKeyboardTapVibePattern; break; + case HapticFeedbackConstants.CLOCK_TICK: + pattern = mClockTickVibePattern; + break; case HapticFeedbackConstants.SAFE_MODE_DISABLED: pattern = mSafeModeDisabledVibePattern; break; @@ -5076,10 +5133,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (pattern.length == 1) { // One-shot vibration - mVibrator.vibrate(owningUid, owningPackage, pattern[0]); + mVibrator.vibrate(owningUid, owningPackage, pattern[0], AudioManager.STREAM_SYSTEM); } else { // Pattern vibration - mVibrator.vibrate(owningUid, owningPackage, pattern, -1); + mVibrator.vibrate(owningUid, owningPackage, pattern, -1, AudioManager.STREAM_SYSTEM); } return true; } @@ -5090,8 +5147,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void keepScreenOnStoppedLw() { - if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotHidden()) { - long curTime = SystemClock.uptimeMillis(); + if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotOccluded()) { mPowerManager.userActivity(SystemClock.uptimeMillis(), false); } } @@ -5103,7 +5159,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (win == null) { return 0; } - if (win.getAttrs().type == TYPE_KEYGUARD && mHideLockScreen == true) { + if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) { // We are updating at a point where the keyguard has gotten // focus, but we were last in a state where the top window is // hiding it. This is probably because the keyguard as been @@ -5113,11 +5169,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } - int tmpVisibility = win.getSystemUiVisibility() + int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) & ~mResettingSystemUiFlags & ~mForceClearedSystemUiFlags; if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { - tmpVisibility &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; + tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); } final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); final int diff = visibility ^ mLastSystemUiFlags; @@ -5149,8 +5205,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { // apply translucent bar vis flags - WindowState transWin = mKeyguard != null && mKeyguard.isVisibleLw() && !mHideLockScreen - ? mKeyguard + WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen + ? mStatusBar : mTopFullscreenOpaqueWindowState; vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis); vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis); @@ -5161,9 +5217,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | View.STATUS_BAR_TRANSLUCENT - | View.NAVIGATION_BAR_TRANSLUCENT; + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + if (!isStatusBarKeyguard() || mHideLockScreen) { + flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; + } vis = (vis & ~flags) | (oldVis & flags); } @@ -5176,7 +5233,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; boolean hideStatusBarWM = mTopFullscreenOpaqueWindowState != null && - (mTopFullscreenOpaqueWindowState.getAttrs().flags + (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; boolean hideStatusBarSysui = (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; @@ -5240,7 +5297,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { * R.boolean.config_enableTranslucentDecor is false. */ private boolean areTranslucentBarsAllowed() { - return mTranslucentDecorEnabled && !mTouchExplorationEnabled; + return mTranslucentDecorEnabled + && !mAccessibilityManager.isTouchExplorationEnabled(); } // Use this instead of checking config_showNavigationBar so that it can be consistently @@ -5257,6 +5315,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + public int getInputMethodWindowVisibleHeightLw() { + return mDockBottom - mCurBottom; + } + + @Override public void setCurrentUserLw(int newUserId) { mCurrentUserId = newUserId; if (mKeyguardDelegate != null) { @@ -5286,11 +5349,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - public void setTouchExplorationEnabled(boolean enabled) { - mTouchExplorationEnabled = enabled; - } - - @Override public boolean isTopLevelWindow(int windowType) { if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { @@ -5407,15 +5465,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBar != null) { pw.print(prefix); pw.print("mStatusBar="); pw.println(mStatusBar); + pw.print(prefix); pw.print("isStatusBarKeyguard="); + pw.print(isStatusBarKeyguard()); } if (mNavigationBar != null) { pw.print(prefix); pw.print("mNavigationBar="); pw.println(mNavigationBar); } - if (mKeyguard != null) { - pw.print(prefix); pw.print("mKeyguard="); - pw.println(mKeyguard); - } if (mFocusedWindow != null) { pw.print(prefix); pw.print("mFocusedWindow="); pw.println(mFocusedWindow); @@ -5460,5 +5516,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); mStatusBarController.dump(pw, prefix); mNavigationBarController.dump(pw, prefix); + PolicyControl.dump(prefix, pw); } } diff --git a/policy/src/com/android/internal/policy/impl/PolicyControl.java b/policy/src/com/android/internal/policy/impl/PolicyControl.java new file mode 100644 index 0000000..ffdb520 --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/PolicyControl.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2014 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; + +import android.content.Context; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.ArraySet; +import android.util.Slog; +import android.view.View; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; +import android.view.WindowManagerPolicy.WindowState; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Runtime adjustments applied to the global window policy. + * + * This includes forcing immersive mode behavior for one or both system bars (based on a package + * list) and permanently disabling immersive mode confirmations for specific packages. + * + * Control by setting {@link Settings.Global.POLICY_CONTROL} to one or more name-value pairs. + * e.g. + * to force immersive mode everywhere: + * "immersive.full=*" + * to force transient status for all apps except a specific package: + * "immersive.status=apps,-com.package" + * to disable the immersive mode confirmations for specific packages: + * "immersive.preconfirms=com.package.one,com.package.two" + * + * Separate multiple name-value pairs with ':' + * e.g. "immersive.status=apps:immersive.preconfirms=*" + */ +public class PolicyControl { + private static String TAG = "PolicyControl"; + private static boolean DEBUG = false; + + private static final String NAME_IMMERSIVE_FULL = "immersive.full"; + private static final String NAME_IMMERSIVE_STATUS = "immersive.status"; + private static final String NAME_IMMERSIVE_NAVIGATION = "immersive.navigation"; + private static final String NAME_IMMERSIVE_PRECONFIRMATIONS = "immersive.preconfirms"; + + private static String sSettingValue; + private static Filter sImmersivePreconfirmationsFilter; + private static Filter sImmersiveStatusFilter; + private static Filter sImmersiveNavigationFilter; + + public static int getSystemUiVisibility(WindowState win, LayoutParams attrs) { + attrs = attrs != null ? attrs : win.getAttrs(); + int vis = win != null ? win.getSystemUiVisibility() : attrs.systemUiVisibility; + if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) { + vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.STATUS_BAR_TRANSLUCENT); + } + if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)) { + vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.NAVIGATION_BAR_TRANSLUCENT); + } + return vis; + } + + public static int getWindowFlags(WindowState win, LayoutParams attrs) { + attrs = attrs != null ? attrs : win.getAttrs(); + int flags = attrs.flags; + if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) { + flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; + flags &= ~(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS + | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } + if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)) { + flags &= ~WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; + } + return flags; + } + + public static int adjustClearableFlags(WindowState win, int clearableFlags) { + final LayoutParams attrs = win != null ? win.getAttrs() : null; + if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) { + clearableFlags &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; + } + return clearableFlags; + } + + public static boolean disableImmersiveConfirmation(String pkg) { + return sImmersivePreconfirmationsFilter != null + && sImmersivePreconfirmationsFilter.matches(pkg); + } + + public static void reloadFromSetting(Context context) { + if (DEBUG) Slog.d(TAG, "reloadFromSetting()"); + String value = null; + try { + value = Settings.Global.getStringForUser(context.getContentResolver(), + Settings.Global.POLICY_CONTROL, + UserHandle.USER_CURRENT); + if (sSettingValue != null && sSettingValue.equals(value)) return; + setFilters(value); + sSettingValue = value; + } catch (Throwable t) { + Slog.w(TAG, "Error loading policy control, value=" + value, t); + } + } + + public static void dump(String prefix, PrintWriter pw) { + dump("sImmersiveStatusFilter", sImmersiveStatusFilter, prefix, pw); + dump("sImmersiveNavigationFilter", sImmersiveNavigationFilter, prefix, pw); + dump("sImmersivePreconfirmationsFilter", sImmersivePreconfirmationsFilter, prefix, pw); + } + + private static void dump(String name, Filter filter, String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("PolicyControl."); pw.print(name); pw.print('='); + if (filter == null) { + pw.println("null"); + } else { + filter.dump(pw); pw.println(); + } + } + + private static void setFilters(String value) { + if (DEBUG) Slog.d(TAG, "setFilters: " + value); + sImmersiveStatusFilter = null; + sImmersiveNavigationFilter = null; + sImmersivePreconfirmationsFilter = null; + if (value != null) { + String[] nvps = value.split(":"); + for (String nvp : nvps) { + int i = nvp.indexOf('='); + if (i == -1) continue; + String n = nvp.substring(0, i); + String v = nvp.substring(i + 1); + if (n.equals(NAME_IMMERSIVE_FULL)) { + Filter f = Filter.parse(v); + sImmersiveStatusFilter = sImmersiveNavigationFilter = f; + if (sImmersivePreconfirmationsFilter == null) { + sImmersivePreconfirmationsFilter = f; + } + } else if (n.equals(NAME_IMMERSIVE_STATUS)) { + Filter f = Filter.parse(v); + sImmersiveStatusFilter = f; + } else if (n.equals(NAME_IMMERSIVE_NAVIGATION)) { + Filter f = Filter.parse(v); + sImmersiveNavigationFilter = f; + if (sImmersivePreconfirmationsFilter == null) { + sImmersivePreconfirmationsFilter = f; + } + } else if (n.equals(NAME_IMMERSIVE_PRECONFIRMATIONS)) { + Filter f = Filter.parse(v); + sImmersivePreconfirmationsFilter = f; + } + } + } + if (DEBUG) { + Slog.d(TAG, "immersiveStatusFilter: " + sImmersiveStatusFilter); + Slog.d(TAG, "immersiveNavigationFilter: " + sImmersiveNavigationFilter); + Slog.d(TAG, "immersivePreconfirmationsFilter: " + sImmersivePreconfirmationsFilter); + } + } + + private static class Filter { + private static final String ALL = "*"; + private static final String APPS = "apps"; + + private final ArraySet<String> mWhitelist; + private final ArraySet<String> mBlacklist; + + private Filter(ArraySet<String> whitelist, ArraySet<String> blacklist) { + mWhitelist = whitelist; + mBlacklist = blacklist; + } + + boolean matches(LayoutParams attrs) { + if (attrs == null) return false; + boolean isApp = attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + && attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; + if (isApp && mBlacklist.contains(APPS)) return false; + if (onBlacklist(attrs.packageName)) return false; + if (isApp && mWhitelist.contains(APPS)) return true; + return onWhitelist(attrs.packageName); + } + + boolean matches(String packageName) { + return !onBlacklist(packageName) && onWhitelist(packageName); + } + + private boolean onBlacklist(String packageName) { + return mBlacklist.contains(packageName) || mBlacklist.contains(ALL); + } + + private boolean onWhitelist(String packageName) { + return mWhitelist.contains(ALL) || mWhitelist.contains(packageName); + } + + void dump(PrintWriter pw) { + pw.print("Filter["); + dump("whitelist", mWhitelist, pw); pw.print(','); + dump("blacklist", mBlacklist, pw); pw.print(']'); + } + + private void dump(String name, ArraySet<String> set, PrintWriter pw) { + pw.print(name); pw.print("=("); + final int n = set.size(); + for (int i = 0; i < n; i++) { + if (i > 0) pw.print(','); + pw.print(set.valueAt(i)); + } + pw.print(')'); + } + + @Override + public String toString() { + StringWriter sw = new StringWriter(); + dump(new PrintWriter(sw, true)); + return sw.toString(); + } + + // value = comma-delimited list of tokens, where token = (package name|apps|*) + // e.g. "com.package1", or "apps, com.android.keyguard" or "*" + static Filter parse(String value) { + if (value == null) return null; + ArraySet<String> whitelist = new ArraySet<String>(); + ArraySet<String> blacklist = new ArraySet<String>(); + for (String token : value.split(",")) { + token = token.trim(); + if (token.startsWith("-") && token.length() > 1) { + token = token.substring(1); + blacklist.add(token); + } else { + whitelist.add(token); + } + } + return new Filter(whitelist, blacklist); + } + } +} diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsBackground.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsBackground.java index 8d87728..3490bd4 100644 --- a/policy/src/com/android/internal/policy/impl/RecentApplicationsBackground.java +++ b/policy/src/com/android/internal/policy/impl/RecentApplicationsBackground.java @@ -21,7 +21,6 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; -import android.util.Log; import android.view.Gravity; import android.view.View; import android.widget.LinearLayout; diff --git a/policy/src/com/android/internal/policy/impl/ShortcutManager.java b/policy/src/com/android/internal/policy/impl/ShortcutManager.java index 75a1b01..bb898f7 100644 --- a/policy/src/com/android/internal/policy/impl/ShortcutManager.java +++ b/policy/src/com/android/internal/policy/impl/ShortcutManager.java @@ -25,7 +25,6 @@ import android.provider.Settings; import android.util.Log; import android.util.SparseArray; import android.view.KeyCharacterMap; -import android.view.KeyEvent; import java.net.URISyntaxException; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java index e5af716..966924b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java @@ -12,7 +12,6 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.util.Slog; -import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -30,8 +29,8 @@ import com.android.internal.widget.LockPatternUtils; */ public class KeyguardServiceDelegate { // TODO: propagate changes to these to {@link KeyguardTouchDelegate} - public static final String KEYGUARD_PACKAGE = "com.android.keyguard"; - public static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService"; + public static final String KEYGUARD_PACKAGE = "com.android.systemui"; + public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService"; private static final String TAG = "KeyguardServiceDelegate"; private static final boolean DEBUG = true; @@ -45,13 +44,13 @@ public class KeyguardServiceDelegate { // the event something checks before the service is actually started. // KeyguardService itself should default to this state until the real state is known. showing = true; - showingAndNotHidden = true; + showingAndNotOccluded = true; secure = true; } boolean showing; - boolean showingAndNotHidden; + boolean showingAndNotOccluded; boolean inputRestricted; - boolean hidden; + boolean occluded; boolean secure; boolean dreaming; boolean systemIsReady; @@ -110,7 +109,7 @@ public class KeyguardServiceDelegate { Context.BIND_AUTO_CREATE, UserHandle.OWNER)) { if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS); mKeyguardState.showing = false; - mKeyguardState.showingAndNotHidden = false; + mKeyguardState.showingAndNotOccluded = false; mKeyguardState.secure = false; } else { if (DEBUG) Log.v(TAG, "*** Keyguard started"); @@ -149,11 +148,11 @@ public class KeyguardServiceDelegate { return mKeyguardState.showing; } - public boolean isShowingAndNotHidden() { + public boolean isShowingAndNotOccluded() { if (mKeyguardService != null) { - mKeyguardState.showingAndNotHidden = mKeyguardService.isShowingAndNotHidden(); + mKeyguardState.showingAndNotOccluded = mKeyguardService.isShowingAndNotOccluded(); } - return mKeyguardState.showingAndNotHidden; + return mKeyguardState.showingAndNotOccluded; } public boolean isInputRestricted() { @@ -175,11 +174,13 @@ public class KeyguardServiceDelegate { } } - public void setHidden(boolean isHidden) { + public int setOccluded(boolean isOccluded) { + int result = 0; if (mKeyguardService != null) { - mKeyguardService.setHidden(isHidden); + result = mKeyguardService.setOccluded(isOccluded); } - mKeyguardState.hidden = isHidden; + mKeyguardState.occluded = isOccluded; + return result; } public void dismiss() { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java index 9fb2a50..7cb48fa 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java @@ -22,6 +22,7 @@ import android.os.RemoteException; import android.util.Slog; import android.view.MotionEvent; +import com.android.internal.policy.IKeyguardServiceConstants; import com.android.internal.policy.IKeyguardShowCallback; import com.android.internal.policy.IKeyguardExitCallback; import com.android.internal.policy.IKeyguardService; @@ -57,9 +58,9 @@ public class KeyguardServiceWrapper implements IKeyguardService { return false; // TODO cache state } - public boolean isShowingAndNotHidden() { + public boolean isShowingAndNotOccluded() { try { - return mService.isShowingAndNotHidden(); + return mService.isShowingAndNotOccluded(); } catch (RemoteException e) { Slog.w(TAG , "Remote Exception", e); } @@ -100,11 +101,12 @@ public class KeyguardServiceWrapper implements IKeyguardService { } } - public void setHidden(boolean isHidden) { + public int setOccluded(boolean isOccluded) { try { - mService.setHidden(isHidden); + return mService.setOccluded(isOccluded); } catch (RemoteException e) { Slog.w(TAG , "Remote Exception", e); + return IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE; } } |