Merge "Simplify immersive mode confirmation cling logic."

This commit is contained in:
John Spurlock
2014-02-12 16:43:48 +00:00
committed by Android (Google) Code Review
2 changed files with 81 additions and 62 deletions

View File

@@ -19,6 +19,7 @@ package com.android.internal.policy.impl;
import android.animation.ArgbEvaluator; import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -27,12 +28,12 @@ import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Slog; import android.util.Slog;
import android.util.SparseBooleanArray;
import android.view.Gravity; import android.view.Gravity;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@@ -46,8 +47,6 @@ import android.widget.FrameLayout;
import com.android.internal.R; import com.android.internal.R;
import java.util.Arrays;
/** /**
* Helper to manage showing/hiding a confirmation prompt when the navigation bar is hidden * Helper to manage showing/hiding a confirmation prompt when the navigation bar is hidden
* entering immersive mode. * entering immersive mode.
@@ -56,19 +55,19 @@ public class ImmersiveModeConfirmation {
private static final String TAG = "ImmersiveModeConfirmation"; private static final String TAG = "ImmersiveModeConfirmation";
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private static final boolean DEBUG_SHOW_EVERY_TIME = false; // super annoying, use with caution 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 Context mContext;
private final H mHandler; private final H mHandler;
private final ArraySet<String> mConfirmedPackages = new ArraySet<String>();
private final long mShowDelayMs; private final long mShowDelayMs;
private final long mPanicThresholdMs; private final long mPanicThresholdMs;
private final SparseBooleanArray mUserPanicResets = new SparseBooleanArray();
private boolean mConfirmed;
private ClingWindowView mClingWindow; private ClingWindowView mClingWindow;
private String mLastPackage;
private String mPromptPackage;
private long mPanicTime; private long mPanicTime;
private String mPanicPackage;
private WindowManager mWindowManager; private WindowManager mWindowManager;
private int mCurrentUserId;
public ImmersiveModeConfirmation(Context context) { public ImmersiveModeConfirmation(Context context) {
mContext = context; mContext = context;
@@ -86,82 +85,91 @@ public class ImmersiveModeConfirmation {
} }
public void loadSetting() { public void loadSetting() {
if (DEBUG) Slog.d(TAG, "loadSetting()"); mConfirmed = false;
mConfirmedPackages.clear(); mCurrentUserId = getCurrentUser();
String packages = null; if (DEBUG) Slog.d(TAG, String.format("loadSetting() mCurrentUserId=%d resetForPanic=%s",
mCurrentUserId, mUserPanicResets.get(mCurrentUserId, false)));
String value = null;
try { try {
packages = Settings.Secure.getStringForUser(mContext.getContentResolver(), value = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS, Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
UserHandle.USER_CURRENT); UserHandle.USER_CURRENT);
if (packages != null) { mConfirmed = CONFIRMED.equals(value);
mConfirmedPackages.addAll(Arrays.asList(packages.split(","))); if (DEBUG) Slog.d(TAG, "Loaded mConfirmed=" + mConfirmed);
if (DEBUG) Slog.d(TAG, "Loaded mConfirmedPackages=" + mConfirmedPackages);
}
} catch (Throwable t) { } catch (Throwable t) {
Slog.w(TAG, "Error loading confirmations, packages=" + packages, t); Slog.w(TAG, "Error loading confirmations, value=" + value, t);
} }
} }
private void saveSetting() { private void saveSetting() {
if (DEBUG) Slog.d(TAG, "saveSetting()"); if (DEBUG) Slog.d(TAG, "saveSetting()");
try { try {
final String packages = TextUtils.join(",", mConfirmedPackages); final String value = mConfirmed ? CONFIRMED : null;
Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS, Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
packages, value,
UserHandle.USER_CURRENT); UserHandle.USER_CURRENT);
if (DEBUG) Slog.d(TAG, "Saved packages=" + packages); if (DEBUG) Slog.d(TAG, "Saved value=" + value);
} catch (Throwable t) { } 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) { public void immersiveModeChanged(String pkg, boolean isImmersiveMode) {
if (pkg == null || PolicyControl.disableImmersiveConfirmation(pkg)) {
return;
}
mHandler.removeMessages(H.SHOW); mHandler.removeMessages(H.SHOW);
if (isImmersiveMode) { if (isImmersiveMode) {
mLastPackage = pkg; final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
if (DEBUG_SHOW_EVERY_TIME || !mConfirmedPackages.contains(pkg)) { if (DEBUG) Slog.d(TAG, String.format("immersiveModeChanged() disabled=%s mConfirmed=%s",
mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs); disabled, mConfirmed));
if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed)) {
mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
} }
} else { } else {
mLastPackage = null;
mHandler.sendEmptyMessage(H.HIDE); mHandler.sendEmptyMessage(H.HIDE);
} }
} }
public void onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) { public boolean onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) {
if (mPanicPackage != null && !isScreenOn && (time - mPanicTime < mPanicThresholdMs)) { if (!isScreenOn && (time - mPanicTime < mPanicThresholdMs)) {
// turning the screen back on within the panic threshold // turning the screen back on within the panic threshold
unconfirmPackage(mPanicPackage); mHandler.sendEmptyMessage(H.PANIC);
return mClingWindow == null;
} }
if (isScreenOn && inImmersiveMode) { if (isScreenOn && inImmersiveMode) {
// turning the screen off, remember if we were in immersive mode // turning the screen off, remember if we were in immersive mode
mPanicTime = time; mPanicTime = time;
mPanicPackage = mLastPackage;
} else { } else {
mPanicTime = 0; mPanicTime = 0;
mPanicPackage = null;
} }
return false;
} }
public void confirmCurrentPrompt() { public void confirmCurrentPrompt() {
mHandler.post(confirmAction(mPromptPackage)); if (mClingWindow != null) {
if (DEBUG) Slog.d(TAG, "confirmCurrentPrompt()");
mHandler.post(mConfirm);
}
} }
private void unconfirmPackage(String pkg) { private void handlePanic() {
if (pkg != null) { if (DEBUG) Slog.d(TAG, "handlePanic()");
if (DEBUG) Slog.d(TAG, "Unconfirming immersive mode confirmation for " + pkg); if (mUserPanicResets.get(mCurrentUserId, false)) return; // already reset for panic
mConfirmedPackages.remove(pkg); mUserPanicResets.put(mCurrentUserId, true);
mConfirmed = false;
saveSetting(); saveSetting();
} }
private int getCurrentUser() {
try {
return ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
throw new IllegalStateException(e); // local call
}
} }
private void handleHide() { private void handleHide() {
if (mClingWindow != null) { 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); mWindowManager.removeView(mClingWindow);
mClingWindow = null; mClingWindow = null;
} }
@@ -297,11 +305,10 @@ public class ImmersiveModeConfirmation {
} }
} }
private void handleShow(String pkg) { private void handleShow() {
mPromptPackage = pkg; if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation");
if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation for " + pkg);
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 // we will be hiding the nav bar, so layout as if it's already hidden
mClingWindow.setSystemUiVisibility( mClingWindow.setSystemUiVisibility(
@@ -313,33 +320,35 @@ public class ImmersiveModeConfirmation {
mWindowManager.addView(mClingWindow, lp); mWindowManager.addView(mClingWindow, lp);
} }
private Runnable confirmAction(final String pkg) { private final Runnable mConfirm = new Runnable() {
return new Runnable() {
@Override @Override
public void run() { public void run() {
if (pkg != null && !mConfirmedPackages.contains(pkg)) { if (DEBUG) Slog.d(TAG, "mConfirm.run()");
if (DEBUG) Slog.d(TAG, "Confirming immersive mode for " + pkg); if (!mConfirmed) {
mConfirmedPackages.add(pkg); mConfirmed = true;
saveSetting(); saveSetting();
} }
handleHide(); handleHide();
} }
}; };
}
private final class H extends Handler { private final class H extends Handler {
private static final int SHOW = 0; private static final int SHOW = 1;
private static final int HIDE = 1; private static final int HIDE = 2;
private static final int PANIC = 3;
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
switch(msg.what) { switch(msg.what) {
case SHOW: case SHOW:
handleShow((String)msg.obj); handleShow();
break; break;
case HIDE: case HIDE:
handleHide(); handleHide();
break; break;
case PANIC:
handlePanic();
break;
} }
} }
} }

View File

@@ -523,7 +523,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
resolver.registerContentObserver(Settings.Secure.getUriFor( resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DEFAULT_INPUT_METHOD), false, this, Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
UserHandle.USER_ALL); UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor( resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this, Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
UserHandle.USER_ALL); UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor( resolver.registerContentObserver(Settings.Global.getUriFor(
@@ -3950,8 +3950,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_POWER: { case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER; result &= ~ACTION_PASS_TO_USER;
if (down) { if (down) {
mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn, event.getDownTime(), boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
isImmersiveMode(mLastSystemUiFlags)); event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
if (panic) {
mHandler.post(mRequestTransientNav);
}
if (isScreenOn && !mPowerKeyTriggered if (isScreenOn && !mPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mPowerKeyTriggered = true; mPowerKeyTriggered = true;
@@ -4218,6 +4221,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} }
}; };
private final Runnable mRequestTransientNav = new Runnable() {
@Override
public void run() {
requestTransientBars(mNavigationBar);
}
};
private void requestTransientBars(WindowState swipeTarget) { private void requestTransientBars(WindowState swipeTarget) {
synchronized (mWindowManagerFuncs.getWindowManagerLock()) { synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
boolean sb = mStatusBarController.checkShowTransientBarLw(); boolean sb = mStatusBarController.checkShowTransientBarLw();