ImmersiveModeConfirmation.java revision da35dded4d7882567eab913b25a7cf2f456d2543
134e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock/* 234e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * Copyright (C) 2013 The Android Open Source Project 334e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * 434e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 534e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * you may not use this file except in compliance with the License. 634e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * You may obtain a copy of the License at 734e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * 834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * http://www.apache.org/licenses/LICENSE-2.0 934e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * 1034e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * Unless required by applicable law or agreed to in writing, software 1134e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 1234e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1334e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * See the License for the specific language governing permissions and 1434e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock * limitations under the License. 1534e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock */ 1634e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 1734e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlockpackage com.android.internal.policy.impl; 1834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 19a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.animation.ArgbEvaluator; 20a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.animation.ValueAnimator; 21a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.app.ActivityManager; 22b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandlerimport android.content.BroadcastReceiver; 2334e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlockimport android.content.Context; 24b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandlerimport android.content.Intent; 25b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandlerimport android.content.IntentFilter; 26a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.graphics.PixelFormat; 27a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.graphics.drawable.ColorDrawable; 2834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlockimport android.os.Handler; 294cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlockimport android.os.Message; 30d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlockimport android.os.UserHandle; 31d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlockimport android.provider.Settings; 32d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlockimport android.text.TextUtils; 3334e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlockimport android.util.ArraySet; 34a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.util.DisplayMetrics; 3534e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlockimport android.util.Slog; 36a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.view.Gravity; 37a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.view.MotionEvent; 3834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlockimport android.view.View; 39a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.view.ViewGroup; 40a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.view.WindowManager; 414cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlockimport android.view.animation.Animation; 424cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlockimport android.view.animation.AnimationUtils; 43a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.view.animation.DecelerateInterpolator; 44a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.widget.Button; 45a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandlerimport android.widget.FrameLayout; 4634e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 4734e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlockimport com.android.internal.R; 4834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 49d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlockimport java.util.Arrays; 50d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock 5134e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock/** 52f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock * Helper to manage showing/hiding a confirmation prompt when the navigation bar is hidden 53f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock * entering immersive mode. 5434e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock */ 55f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlockpublic class ImmersiveModeConfirmation { 56f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock private static final String TAG = "ImmersiveModeConfirmation"; 574cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private static final boolean DEBUG = false; 58a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private static final boolean DEBUG_SHOW_EVERY_TIME = false; // super annoying, use with caution 5934e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 6034e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock private final Context mContext; 614cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private final H mHandler; 62d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private final ArraySet<String> mConfirmedPackages = new ArraySet<String>(); 634cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private final long mShowDelayMs; 64d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private final long mPanicThresholdMs; 6534e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 66a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private ClingWindowView mClingWindow; 67d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private String mLastPackage; 68d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private String mPromptPackage; 69d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private long mPanicTime; 70d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private String mPanicPackage; 71a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private WindowManager mWindowManager; 7234e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 73f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock public ImmersiveModeConfirmation(Context context) { 7434e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock mContext = context; 754cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock mHandler = new H(); 764cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock mShowDelayMs = getNavBarExitDuration() * 3; 77d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mPanicThresholdMs = context.getResources() 78f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock .getInteger(R.integer.config_immersive_mode_confirmation_panic); 79a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mWindowManager = (WindowManager) 80a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mContext.getSystemService(Context.WINDOW_SERVICE); 814cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock } 824cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock 834cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private long getNavBarExitDuration() { 844cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock Animation exit = AnimationUtils.loadAnimation(mContext, R.anim.dock_bottom_exit); 854cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock return exit != null ? exit.getDuration() : 0; 8634e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 8734e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 88d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock public void loadSetting() { 89d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (DEBUG) Slog.d(TAG, "loadSetting()"); 90d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mConfirmedPackages.clear(); 91d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock String packages = null; 92d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock try { 93d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock packages = Settings.Secure.getStringForUser(mContext.getContentResolver(), 94f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS, 95d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock UserHandle.USER_CURRENT); 96d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (packages != null) { 97d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mConfirmedPackages.addAll(Arrays.asList(packages.split(","))); 98d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (DEBUG) Slog.d(TAG, "Loaded mConfirmedPackages=" + mConfirmedPackages); 99d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 100d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } catch (Throwable t) { 101d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock Slog.w(TAG, "Error loading confirmations, packages=" + packages, t); 102d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 103d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 104d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock 105d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private void saveSetting() { 106d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (DEBUG) Slog.d(TAG, "saveSetting()"); 107d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock try { 108d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock final String packages = TextUtils.join(",", mConfirmedPackages); 109d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock Settings.Secure.putStringForUser(mContext.getContentResolver(), 110f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS, 111d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock packages, 112d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock UserHandle.USER_CURRENT); 113d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (DEBUG) Slog.d(TAG, "Saved packages=" + packages); 114d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } catch (Throwable t) { 115d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock Slog.w(TAG, "Error saving confirmations, mConfirmedPackages=" + mConfirmedPackages, t); 116d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 117d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 118d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock 119f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock public void immersiveModeChanged(String pkg, boolean isImmersiveMode) { 12034e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock if (pkg == null) { 12134e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock return; 12234e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 1234cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock mHandler.removeMessages(H.SHOW); 124f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock if (isImmersiveMode) { 125d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mLastPackage = pkg; 126a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler if (DEBUG_SHOW_EVERY_TIME || !mConfirmedPackages.contains(pkg)) { 127d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs); 12834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 12934e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } else { 130d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mLastPackage = null; 1314cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock mHandler.sendEmptyMessage(H.HIDE); 13234e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 13334e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 13434e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 135f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock public void onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) { 136d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (mPanicPackage != null && !isScreenOn && (time - mPanicTime < mPanicThresholdMs)) { 137d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock // turning the screen back on within the panic threshold 138d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock unconfirmPackage(mPanicPackage); 139d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 140f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock if (isScreenOn && inImmersiveMode) { 141f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock // turning the screen off, remember if we were in immersive mode 142d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mPanicTime = time; 143d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mPanicPackage = mLastPackage; 144d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } else { 145d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mPanicTime = 0; 146d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mPanicPackage = null; 147d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 148d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 149d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock 150d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock public void confirmCurrentPrompt() { 151d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mHandler.post(confirmAction(mPromptPackage)); 152d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 153d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock 154d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private void unconfirmPackage(String pkg) { 155d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (pkg != null) { 156f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock if (DEBUG) Slog.d(TAG, "Unconfirming immersive mode confirmation for " + pkg); 157d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mConfirmedPackages.remove(pkg); 158d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock saveSetting(); 15934e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 16034e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 16134e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 1624cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private void handleHide() { 163a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler if (mClingWindow != null) { 164f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation for " + mPromptPackage); 165a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mWindowManager.removeView(mClingWindow); 166a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mClingWindow = null; 167a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } 168a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } 169a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 170b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler public WindowManager.LayoutParams getClingWindowLayoutParams() { 171b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 172b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler ViewGroup.LayoutParams.MATCH_PARENT, 173b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler ViewGroup.LayoutParams.MATCH_PARENT, 174b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler WindowManager.LayoutParams.TYPE_TOAST, 175b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler 0 176b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 177b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 178b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED 179b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler , 180b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler PixelFormat.TRANSLUCENT); 181f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock lp.setTitle("ImmersiveModeConfirmation"); 182b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications; 183b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler lp.gravity = Gravity.FILL; 184b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler return lp; 185b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler } 186b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler 187b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler public FrameLayout.LayoutParams getBubbleLayoutParams() { 188b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler return new FrameLayout.LayoutParams( 189b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler mContext.getResources().getDimensionPixelSize( 190b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler R.dimen.immersive_mode_cling_width), 191b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler ViewGroup.LayoutParams.WRAP_CONTENT, 192b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler Gravity.CENTER_HORIZONTAL | Gravity.TOP); 193b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler } 194b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler 195a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private class ClingWindowView extends FrameLayout { 196a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private static final int BGCOLOR = 0x80000000; 197a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private static final int OFFSET_DP = 48; 198a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 19947e3de2baa59b6d8ad7de0f569a814877f287a7eJohn Spurlock private final Runnable mConfirm; 200a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private final ColorDrawable mColor = new ColorDrawable(0); 201a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler private ValueAnimator mColorAnim; 202b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler private ViewGroup mClingLayout; 203b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler 204da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler private Runnable mUpdateLayoutRunnable = new Runnable() { 205da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler @Override 206da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler public void run() { 207da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler if (mClingLayout != null && mClingLayout.getParent() != null) { 208da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler mClingLayout.setLayoutParams(getBubbleLayoutParams()); 209da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler } 210da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler } 211da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler }; 212da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler 213b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler private BroadcastReceiver mReceiver = new BroadcastReceiver() { 214b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler @Override 215b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler public void onReceive(Context context, Intent intent) { 216b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler if (intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 217da35dded4d7882567eab913b25a7cf2f456d2543Daniel Sandler post(mUpdateLayoutRunnable); 218b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler } 219b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler } 220b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler }; 221a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 22247e3de2baa59b6d8ad7de0f569a814877f287a7eJohn Spurlock public ClingWindowView(Context context, Runnable confirm) { 223a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler super(context); 22447e3de2baa59b6d8ad7de0f569a814877f287a7eJohn Spurlock mConfirm = confirm; 225a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler setClickable(true); 226a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler setBackground(mColor); 227a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } 228a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 229a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler @Override 230a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler public void onAttachedToWindow() { 231a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler super.onAttachedToWindow(); 232a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 233a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler DisplayMetrics metrics = new DisplayMetrics(); 234a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mWindowManager.getDefaultDisplay().getMetrics(metrics); 235a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler float density = metrics.density; 236a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 237a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler // create the confirmation cling 238b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler mClingLayout = (ViewGroup) 239f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock View.inflate(getContext(), R.layout.immersive_mode_cling, null); 240a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 241b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler final Button ok = (Button) mClingLayout.findViewById(R.id.ok); 242a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler ok.setOnClickListener(new OnClickListener() { 243a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler @Override 244a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler public void onClick(View v) { 24547e3de2baa59b6d8ad7de0f569a814877f287a7eJohn Spurlock mConfirm.run(); 246a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } 247a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler }); 248b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler addView(mClingLayout, getBubbleLayoutParams()); 249a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 250a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler if (ActivityManager.isHighEndGfx()) { 251b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler final View bubble = mClingLayout.findViewById(R.id.text); 252a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler bubble.setAlpha(0f); 253a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler bubble.setTranslationY(-OFFSET_DP*density); 254a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler bubble.animate() 255a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .alpha(1f) 256a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .translationY(0) 257a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .setDuration(300) 258a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .setInterpolator(new DecelerateInterpolator()) 259a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .start(); 260a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 261a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler ok.setAlpha(0f); 262a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler ok.setTranslationY(-OFFSET_DP*density); 263a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler ok.animate().alpha(1f) 264a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .translationY(0) 265a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .setDuration(300) 266a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .setStartDelay(200) 267a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .setInterpolator(new DecelerateInterpolator()) 268a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler .start(); 269a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 270a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mColorAnim = ValueAnimator.ofObject(new ArgbEvaluator(), 0, BGCOLOR); 271a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 272a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler @Override 273a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler public void onAnimationUpdate(ValueAnimator animation) { 274a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler final int c = (Integer) animation.getAnimatedValue(); 275a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mColor.setColor(c); 276a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } 277a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler }); 278a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mColorAnim.setDuration(1000); 279a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mColorAnim.start(); 280a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } else { 281a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mColor.setColor(BGCOLOR); 282a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } 283b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler 284b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler mContext.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)); 285b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler } 286b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler 287b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler @Override 288b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler public void onDetachedFromWindow() { 289b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler mContext.unregisterReceiver(mReceiver); 290a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler } 291a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler 292a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler @Override 293a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler public boolean onTouchEvent(MotionEvent motion) { 294a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler Slog.v(TAG, "ClingWindowView.onTouchEvent"); 295a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler return true; 2964cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock } 2974cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock } 29834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 299d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private void handleShow(String pkg) { 300d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mPromptPackage = pkg; 301f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation for " + pkg); 302d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock 30347e3de2baa59b6d8ad7de0f569a814877f287a7eJohn Spurlock mClingWindow = new ClingWindowView(mContext, confirmAction(pkg)); 30434e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 3054cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock // we will be hiding the nav bar, so layout as if it's already hidden 306a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mClingWindow.setSystemUiVisibility( 307a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 308a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 3094cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock 3104cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock // show the confirmation 311b83f5c6a421c476a0f1af6e986a88f073581afd2Daniel Sandler WindowManager.LayoutParams lp = getClingWindowLayoutParams(); 312a953b6d968beba01baad095b9ed2e40dbb97f189Daniel Sandler mWindowManager.addView(mClingWindow, lp); 31334e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 31434e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock 315d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock private Runnable confirmAction(final String pkg) { 31634e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock return new Runnable() { 31734e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock @Override 31834e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock public void run() { 319d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock if (pkg != null && !mConfirmedPackages.contains(pkg)) { 320f1a36648ca099d7ffa8a19e403673820d4b8417aJohn Spurlock if (DEBUG) Slog.d(TAG, "Confirming immersive mode for " + pkg); 321d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock mConfirmedPackages.add(pkg); 322d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock saveSetting(); 323d67ec25a9c4bf728e4805248d0b287cc3c3ab8aeJohn Spurlock } 3244cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock handleHide(); 32534e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 32634e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock }; 32734e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock } 3284cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock 3294cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private final class H extends Handler { 3304cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private static final int SHOW = 0; 3314cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock private static final int HIDE = 1; 3324cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock 3334cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock @Override 3344cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock public void handleMessage(Message msg) { 3354cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock switch(msg.what) { 3364cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock case SHOW: 3374cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock handleShow((String)msg.obj); 3384cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock break; 3394cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock case HIDE: 3404cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock handleHide(); 3414cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock break; 3424cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock } 3434cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock } 3444cf6a948f9998204d2bfdceebae89954b2b4ae7eJohn Spurlock } 34534e13d90eda9bfda7a70998d190a95c88aa3d3d1John Spurlock} 346