blob: d9e09034eb2afbd0f61a1eccdd88660dcb4d3c20 [file] [log] [blame]
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar.phone;
18
John Spurlock1bbd49d2012-10-19 11:09:32 -040019import android.animation.LayoutTransition;
John Spurlock56d007b2013-10-28 18:40:56 -040020import android.animation.LayoutTransition.TransitionListener;
21import android.animation.ObjectAnimator;
22import android.animation.TimeInterpolator;
23import android.animation.ValueAnimator;
Jim Millercaf24fc2013-09-10 18:37:01 -070024import android.app.ActivityManagerNative;
Daniel Sandler328310c2011-09-23 15:56:52 -040025import android.app.StatusBarManager;
Jim Millercaf24fc2013-09-10 18:37:01 -070026import android.app.admin.DevicePolicyManager;
27import android.content.BroadcastReceiver;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040028import android.content.Context;
Jim Millercaf24fc2013-09-10 18:37:01 -070029import android.content.Intent;
30import android.content.IntentFilter;
Daniel Sandler60ee2562011-07-22 12:34:33 -040031import android.content.res.Resources;
Jeff Browna8b9def2012-07-23 14:22:49 -070032import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050033import android.graphics.Rect;
Daniel Sandler2c9ae752012-04-27 00:14:54 -040034import android.graphics.drawable.Drawable;
Daniel Sandler0b69b592012-01-23 21:08:36 -050035import android.os.Handler;
36import android.os.Message;
Jim Millercaf24fc2013-09-10 18:37:01 -070037import android.os.RemoteException;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040038import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040039import android.util.Log;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040040import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040041import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040042import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040043import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040044import android.view.ViewGroup;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040045import android.view.WindowManager;
Jim Miller138f25d2013-09-25 13:46:58 -070046import android.view.accessibility.AccessibilityManager;
Jim Miller7d8abae2013-10-08 21:10:40 -070047import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
Daniel Sandler328310c2011-09-23 15:56:52 -040048import android.widget.ImageView;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040049import android.widget.LinearLayout;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040050
51import com.android.systemui.R;
Jim Millere898ac52012-04-06 17:10:57 -070052import com.android.systemui.statusbar.BaseStatusBar;
53import com.android.systemui.statusbar.DelegateViewHelper;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040054import com.android.systemui.statusbar.policy.DeadZone;
John Spurlock56d007b2013-10-28 18:40:56 -040055import com.android.systemui.statusbar.policy.KeyButtonView;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040056
John Spurlockde84f0e2013-06-12 12:41:00 -040057import java.io.FileDescriptor;
58import java.io.PrintWriter;
59
Adrian Roos5b0acf02014-01-10 12:58:22 -080060import static com.android.systemui.statusbar.phone.KeyguardTouchDelegate.OnKeyguardConnectionListener;
61
Daniel Sandler8956dbb2011-04-22 07:55:02 -040062public class NavigationBarView extends LinearLayout {
Daniel Sandler60ee2562011-07-22 12:34:33 -040063 final static boolean DEBUG = false;
Daniel Sandler6da2b762011-09-14 16:04:59 -040064 final static String TAG = "PhoneStatusBar/NavigationBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040065
Daniel Sandlerf86f8982011-05-31 15:46:13 -040066 final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
67
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040068 // slippery nav bar when everything is disabled, e.g. during setup
John Spurlock7edfbca2013-09-14 11:58:55 -040069 final static boolean SLIPPERY_WHEN_DISABLED = true;
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040070
Daniel Sandler8956dbb2011-04-22 07:55:02 -040071 final Display mDisplay;
Daniel Sandler5c8da942011-06-28 00:29:04 -040072 View mCurrentView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040073 View[] mRotatedViews = new View[4];
Daniel Sandler60ee2562011-07-22 12:34:33 -040074
75 int mBarSize;
76 boolean mVertical;
John Spurlock1bbd49d2012-10-19 11:09:32 -040077 boolean mScreenOn;
Daniel Sandler60ee2562011-07-22 12:34:33 -040078
John Spurlock7edfbca2013-09-14 11:58:55 -040079 boolean mShowMenu;
Daniel Sandler6da2b762011-09-14 16:04:59 -040080 int mDisabledFlags = 0;
Daniel Sandler328310c2011-09-23 15:56:52 -040081 int mNavigationIconHints = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040082
Daniel Sandler2c9ae752012-04-27 00:14:54 -040083 private Drawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -070084 private Drawable mRecentIcon;
Fabrice Di Meglio18d98242013-01-17 10:57:40 -080085 private Drawable mRecentLandIcon;
86
Jim Millere898ac52012-04-06 17:10:57 -070087 private DelegateViewHelper mDelegateHelper;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040088 private DeadZone mDeadZone;
John Spurlock89835dd2013-08-16 15:06:51 -040089 private final NavigationBarTransitions mBarTransitions;
Jim Millere898ac52012-04-06 17:10:57 -070090
Daniel Sandler0b69b592012-01-23 21:08:36 -050091 // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
92 final static boolean WORKAROUND_INVALID_LAYOUT = true;
93 final static int MSG_CHECK_INVALID_LAYOUT = 8686;
94
Jim Millercaf24fc2013-09-10 18:37:01 -070095 // used to disable the camera icon in navbar when disabled by DPM
96 private boolean mCameraDisabledByDpm;
Jim Millercaf24fc2013-09-10 18:37:01 -070097
John Spurlock56d007b2013-10-28 18:40:56 -040098 // performs manual animation in sync with layout transitions
99 private final NavTransitionListener mTransitionListener = new NavTransitionListener();
100
101 private class NavTransitionListener implements TransitionListener {
102 private boolean mBackTransitioning;
103 private boolean mHomeAppearing;
104 private long mStartDelay;
105 private long mDuration;
106 private TimeInterpolator mInterpolator;
107
108 @Override
109 public void startTransition(LayoutTransition transition, ViewGroup container,
110 View view, int transitionType) {
111 if (view.getId() == R.id.back) {
112 mBackTransitioning = true;
113 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
114 mHomeAppearing = true;
115 mStartDelay = transition.getStartDelay(transitionType);
116 mDuration = transition.getDuration(transitionType);
117 mInterpolator = transition.getInterpolator(transitionType);
118 }
119 }
120
121 @Override
122 public void endTransition(LayoutTransition transition, ViewGroup container,
123 View view, int transitionType) {
124 if (view.getId() == R.id.back) {
125 mBackTransitioning = false;
126 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
127 mHomeAppearing = false;
128 }
129 }
130
131 public void onBackAltCleared() {
132 // When dismissing ime during unlock, force the back button to run the same appearance
133 // animation as home (if we catch this condition early enough).
134 if (!mBackTransitioning && getBackButton().getVisibility() == VISIBLE
135 && mHomeAppearing && getHomeButton().getAlpha() == 0) {
136 getBackButton().setAlpha(0);
137 ValueAnimator a = ObjectAnimator.ofFloat(getBackButton(), "alpha", 0, 1);
138 a.setStartDelay(mStartDelay);
139 a.setDuration(mDuration);
140 a.setInterpolator(mInterpolator);
141 a.start();
142 }
143 }
144 }
145
Jim Miller7d8abae2013-10-08 21:10:40 -0700146 // simplified click handler to be used when device is in accessibility mode
147 private final OnClickListener mAccessibilityClickListener = new OnClickListener() {
148 @Override
149 public void onClick(View v) {
150 if (v.getId() == R.id.camera_button) {
151 KeyguardTouchDelegate.getInstance(getContext()).launchCamera();
152 } else if (v.getId() == R.id.search_light) {
153 KeyguardTouchDelegate.getInstance(getContext()).showAssistant();
154 }
155 }
156 };
157
Jim Millercaf24fc2013-09-10 18:37:01 -0700158 private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
159 @Override
Jim Millerf4db8f92013-09-20 14:21:50 -0700160 public boolean onTouch(View cameraButtonView, MotionEvent event) {
Jim Millerf4db8f92013-09-20 14:21:50 -0700161 switch (event.getAction()) {
162 case MotionEvent.ACTION_DOWN:
163 // disable search gesture while interacting with camera
164 mDelegateHelper.setDisabled(true);
John Spurlock56d007b2013-10-28 18:40:56 -0400165 mBarTransitions.setContentVisible(false);
Jim Millerf4db8f92013-09-20 14:21:50 -0700166 break;
167 case MotionEvent.ACTION_UP:
168 case MotionEvent.ACTION_CANCEL:
169 mDelegateHelper.setDisabled(false);
John Spurlock56d007b2013-10-28 18:40:56 -0400170 mBarTransitions.setContentVisible(true);
Jim Millerf4db8f92013-09-20 14:21:50 -0700171 break;
172 }
Jim Miller6c9df502013-09-19 15:50:11 -0700173 return KeyguardTouchDelegate.getInstance(getContext()).dispatch(event);
Jim Millercaf24fc2013-09-10 18:37:01 -0700174 }
175 };
176
Adrian Roos5b0acf02014-01-10 12:58:22 -0800177 private final OnKeyguardConnectionListener mKeyguardConnectionListener =
178 new OnKeyguardConnectionListener() {
179 @Override
180 public void onKeyguardServiceConnected(
181 KeyguardTouchDelegate keyguardTouchDelegate) {
182 post(new Runnable() {
183 @Override
184 public void run() {
185 mCameraDisabledByDpm = isCameraDisabledByDpm();
186 }
187 });
188 }
189
190 @Override
191 public void onKeyguardServiceDisconnected(
192 KeyguardTouchDelegate keyguardTouchDelegate) {
193 }
194 };
195
Daniel Sandler0b69b592012-01-23 21:08:36 -0500196 private class H extends Handler {
197 public void handleMessage(Message m) {
198 switch (m.what) {
199 case MSG_CHECK_INVALID_LAYOUT:
200 final String how = "" + m.obj;
201 final int w = getWidth();
202 final int h = getHeight();
203 final int vw = mCurrentView.getWidth();
204 final int vh = mCurrentView.getHeight();
205
206 if (h != vh || w != vw) {
John Spurlockcd686b52013-06-05 10:13:46 -0400207 Log.w(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500208 "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)",
209 how, w, h, vw, vh));
210 if (WORKAROUND_INVALID_LAYOUT) {
211 requestLayout();
212 }
213 }
214 break;
215 }
216 }
217 }
218
John Spurlocke932e302013-08-12 10:16:29 -0400219 public NavigationBarView(Context context, AttributeSet attrs) {
220 super(context, attrs);
221
John Spurlocke932e302013-08-12 10:16:29 -0400222 mDisplay = ((WindowManager)context.getSystemService(
223 Context.WINDOW_SERVICE)).getDefaultDisplay();
John Spurlocke932e302013-08-12 10:16:29 -0400224
John Spurlock01534782014-01-13 11:59:22 -0500225 final Resources res = getContext().getResources();
John Spurlocke932e302013-08-12 10:16:29 -0400226 mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
227 mVertical = false;
228 mShowMenu = false;
229 mDelegateHelper = new DelegateViewHelper(this);
230
231 getIcons(res);
232
John Spurlock7edfbca2013-09-14 11:58:55 -0400233 mBarTransitions = new NavigationBarTransitions(this);
Jim Millercaf24fc2013-09-10 18:37:01 -0700234
Adrian Roos5b0acf02014-01-10 12:58:22 -0800235 KeyguardTouchDelegate.addListener(mKeyguardConnectionListener);
Jim Millercaf24fc2013-09-10 18:37:01 -0700236 mCameraDisabledByDpm = isCameraDisabledByDpm();
237 watchForDevicePolicyChanges();
238 }
239
240 private void watchForDevicePolicyChanges() {
241 final IntentFilter filter = new IntentFilter();
242 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
John Spurlock01534782014-01-13 11:59:22 -0500243 getContext().registerReceiver(new BroadcastReceiver() {
Jim Millercaf24fc2013-09-10 18:37:01 -0700244 public void onReceive(Context context, Intent intent) {
245 post(new Runnable() {
246 @Override
247 public void run() {
248 mCameraDisabledByDpm = isCameraDisabledByDpm();
249 }
250 });
251 }
252 }, filter);
John Spurlocke932e302013-08-12 10:16:29 -0400253 }
254
255 public BarTransitions getBarTransitions() {
256 return mBarTransitions;
257 }
258
Jim Millere898ac52012-04-06 17:10:57 -0700259 public void setDelegateView(View view) {
260 mDelegateHelper.setDelegateView(view);
261 }
262
263 public void setBar(BaseStatusBar phoneStatusBar) {
264 mDelegateHelper.setBar(phoneStatusBar);
265 }
266
267 @Override
Jim Miller960892c2012-05-23 15:50:04 -0700268 public boolean onTouchEvent(MotionEvent event) {
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400269 if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
270 mDeadZone.poke(event);
Jim Miller960892c2012-05-23 15:50:04 -0700271 }
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400272 if (mDelegateHelper != null) {
273 boolean ret = mDelegateHelper.onInterceptTouchEvent(event);
274 if (ret) return true;
275 }
276 return super.onTouchEvent(event);
Jim Miller960892c2012-05-23 15:50:04 -0700277 }
278
279 @Override
Jim Millere898ac52012-04-06 17:10:57 -0700280 public boolean onInterceptTouchEvent(MotionEvent event) {
281 return mDelegateHelper.onInterceptTouchEvent(event);
282 }
283
Daniel Sandler0b69b592012-01-23 21:08:36 -0500284 private H mHandler = new H();
285
John Spurlock7edfbca2013-09-14 11:58:55 -0400286 public View getCurrentView() {
287 return mCurrentView;
288 }
289
Daniel Sandler5c8da942011-06-28 00:29:04 -0400290 public View getRecentsButton() {
291 return mCurrentView.findViewById(R.id.recent_apps);
292 }
293
294 public View getMenuButton() {
295 return mCurrentView.findViewById(R.id.menu);
296 }
297
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400298 public View getBackButton() {
299 return mCurrentView.findViewById(R.id.back);
300 }
301
302 public View getHomeButton() {
303 return mCurrentView.findViewById(R.id.home);
304 }
305
Daniel Sandlerd5483c32012-10-19 16:44:15 -0400306 // for when home is disabled, but search isn't
307 public View getSearchLight() {
308 return mCurrentView.findViewById(R.id.search_light);
309 }
310
Jim Millercaf24fc2013-09-10 18:37:01 -0700311 // shown when keyguard is visible and camera is available
312 public View getCameraButton() {
313 return mCurrentView.findViewById(R.id.camera_button);
314 }
315
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700316 private void getIcons(Resources res) {
Daniel Sandler2c9ae752012-04-27 00:14:54 -0400317 mBackIcon = res.getDrawable(R.drawable.ic_sysbar_back);
318 mBackLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_land);
319 mBackAltIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
320 mBackAltLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700321 mRecentIcon = res.getDrawable(R.drawable.ic_sysbar_recent);
Fabrice Di Meglio18d98242013-01-17 10:57:40 -0800322 mRecentLandIcon = res.getDrawable(R.drawable.ic_sysbar_recent_land);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700323 }
324
325 @Override
326 public void setLayoutDirection(int layoutDirection) {
John Spurlock01534782014-01-13 11:59:22 -0500327 getIcons(getContext().getResources());
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700328
329 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400330 }
331
John Spurlock1bbd49d2012-10-19 11:09:32 -0400332 public void notifyScreenOn(boolean screenOn) {
333 mScreenOn = screenOn;
334 setDisabledFlags(mDisabledFlags, true);
335 }
336
Daniel Sandler328310c2011-09-23 15:56:52 -0400337 public void setNavigationIconHints(int hints) {
338 setNavigationIconHints(hints, false);
339 }
340
341 public void setNavigationIconHints(int hints, boolean force) {
342 if (!force && hints == mNavigationIconHints) return;
John Spurlock56d007b2013-10-28 18:40:56 -0400343 final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
344 if ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 && !backAlt) {
345 mTransitionListener.onBackAltCleared();
346 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400347 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500348 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400349 "Navigation icon hints = " + hints,
350 500).show();
351 }
352
353 mNavigationIconHints = hints;
354
John Spurlock56d007b2013-10-28 18:40:56 -0400355 ((ImageView)getBackButton()).setImageDrawable(backAlt
Daniel Sandler2c9ae752012-04-27 00:14:54 -0400356 ? (mVertical ? mBackAltLandIcon : mBackAltIcon)
357 : (mVertical ? mBackLandIcon : mBackIcon));
John Spurlocka9b46822012-11-02 10:42:39 -0400358
Fabrice Di Meglio18d98242013-01-17 10:57:40 -0800359 ((ImageView)getRecentsButton()).setImageDrawable(mVertical ? mRecentLandIcon : mRecentIcon);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700360
John Spurlocka9b46822012-11-02 10:42:39 -0400361 setDisabledFlags(mDisabledFlags, true);
Daniel Sandler328310c2011-09-23 15:56:52 -0400362 }
363
Daniel Sandler6da2b762011-09-14 16:04:59 -0400364 public void setDisabledFlags(int disabledFlags) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400365 setDisabledFlags(disabledFlags, false);
366 }
367
368 public void setDisabledFlags(int disabledFlags, boolean force) {
369 if (!force && mDisabledFlags == disabledFlags) return;
370
371 mDisabledFlags = disabledFlags;
372
Daniel Sandlerdba93562011-10-06 16:39:58 -0400373 final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
374 final boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
John Spurlocka9b46822012-11-02 10:42:39 -0400375 final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
376 && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
Daniel Sandlerd5483c32012-10-19 16:44:15 -0400377 final boolean disableSearch = ((disabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0);
Daniel Sandler029d5872011-09-12 00:58:58 -0400378
Daniel Sandlerc3fc3222012-10-25 13:28:33 -0400379 if (SLIPPERY_WHEN_DISABLED) {
380 setSlippery(disableHome && disableRecent && disableBack && disableSearch);
381 }
John Spurlockd5ef5462012-06-13 11:19:51 -0400382
John Spurlock56d007b2013-10-28 18:40:56 -0400383 ViewGroup navButtons = (ViewGroup) mCurrentView.findViewById(R.id.nav_buttons);
384 if (navButtons != null) {
385 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400386 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400387 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
388 lt.addTransitionListener(mTransitionListener);
389 }
390 if (!mScreenOn && mCurrentView != null) {
391 lt.disableTransitionType(
392 LayoutTransition.CHANGE_APPEARING |
393 LayoutTransition.CHANGE_DISAPPEARING |
394 LayoutTransition.APPEARING |
395 LayoutTransition.DISAPPEARING);
396 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400397 }
398 }
399
Daniel Sandler029d5872011-09-12 00:58:58 -0400400 getBackButton() .setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Daniel Sandlerdba93562011-10-06 16:39:58 -0400401 getHomeButton() .setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
402 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
Daniel Sandlerd5483c32012-10-19 16:44:15 -0400403
John Spurlock56d007b2013-10-28 18:40:56 -0400404 final boolean showSearch = disableHome && !disableSearch;
405 final boolean showCamera = showSearch && !mCameraDisabledByDpm;
406 setVisibleOrGone(getSearchLight(), showSearch);
407 setVisibleOrGone(getCameraButton(), showCamera);
408
409 mBarTransitions.applyBackButtonQuiescentAlpha(mBarTransitions.getMode(), true /*animate*/);
410 }
411
412 private void setVisibleOrGone(View view, boolean visible) {
413 if (view != null) {
414 view.setVisibility(visible ? VISIBLE : GONE);
Jim Millercaf24fc2013-09-10 18:37:01 -0700415 }
416 }
417
418 private boolean isCameraDisabledByDpm() {
419 final DevicePolicyManager dpm =
John Spurlock01534782014-01-13 11:59:22 -0500420 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
Jim Millercaf24fc2013-09-10 18:37:01 -0700421 if (dpm != null) {
422 try {
423 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
424 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
425 final boolean disabledBecauseKeyguardSecure =
426 (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
Jim Miller6c9df502013-09-19 15:50:11 -0700427 && KeyguardTouchDelegate.getInstance(getContext()).isSecure();
Jim Millercaf24fc2013-09-10 18:37:01 -0700428 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
429 } catch (RemoteException e) {
430 Log.e(TAG, "Can't get userId", e);
431 }
432 }
433 return false;
Daniel Sandler56598cd2011-09-15 16:02:56 -0400434 }
435
John Spurlockd5ef5462012-06-13 11:19:51 -0400436 public void setSlippery(boolean newSlippery) {
437 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
438 if (lp != null) {
439 boolean oldSlippery = (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0;
440 if (!oldSlippery && newSlippery) {
441 lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
442 } else if (oldSlippery && !newSlippery) {
443 lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
444 } else {
445 return;
446 }
Jeff Brown98365d72012-08-19 20:30:52 -0700447 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
448 wm.updateViewLayout(this, lp);
John Spurlockd5ef5462012-06-13 11:19:51 -0400449 }
450 }
451
Daniel Sandler56598cd2011-09-15 16:02:56 -0400452 public void setMenuVisibility(final boolean show) {
453 setMenuVisibility(show, false);
454 }
455
456 public void setMenuVisibility(final boolean show, final boolean force) {
457 if (!force && mShowMenu == show) return;
458
459 mShowMenu = show;
460
Daniel Sandlerdba93562011-10-06 16:39:58 -0400461 getMenuButton().setVisibility(mShowMenu ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400462 }
463
Jim Miller960892c2012-05-23 15:50:04 -0700464 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400465 public void onFinishInflate() {
John Spurlock209bede2013-07-17 12:23:27 -0400466 mRotatedViews[Surface.ROTATION_0] =
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400467 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
468
469 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
John Spurlock209bede2013-07-17 12:23:27 -0400470
Daniel Sandlerf86f8982011-05-31 15:46:13 -0400471 mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
472 ? findViewById(R.id.rot90)
473 : findViewById(R.id.rot270);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400474
475 mCurrentView = mRotatedViews[Surface.ROTATION_0];
Jim Millercaf24fc2013-09-10 18:37:01 -0700476
Jim Miller7d8abae2013-10-08 21:10:40 -0700477 watchForAccessibilityChanges();
Jim Miller138f25d2013-09-25 13:46:58 -0700478 }
479
Jim Miller7d8abae2013-10-08 21:10:40 -0700480 private void watchForAccessibilityChanges() {
481 final AccessibilityManager am =
John Spurlock01534782014-01-13 11:59:22 -0500482 (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
Jim Miller7d8abae2013-10-08 21:10:40 -0700483
484 // Set the initial state
485 enableAccessibility(am.isTouchExplorationEnabled());
486
487 // Watch for changes
488 am.addTouchExplorationStateChangeListener(new TouchExplorationStateChangeListener() {
489 @Override
490 public void onTouchExplorationStateChanged(boolean enabled) {
491 enableAccessibility(enabled);
492 }
493 });
494 }
495
496 private void enableAccessibility(boolean touchEnabled) {
497 Log.v(TAG, "touchEnabled:" + touchEnabled);
498
499 // Add a touch handler or accessibility click listener for camera and search buttons
500 // for all view orientations.
501 final OnClickListener onClickListener = touchEnabled ? mAccessibilityClickListener : null;
502 final OnTouchListener onTouchListener = touchEnabled ? null : mCameraTouchListener;
503 boolean hasCamera = false;
504 for (int i = 0; i < mRotatedViews.length; i++) {
505 final View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button);
506 final View searchLight = mRotatedViews[i].findViewById(R.id.search_light);
507 if (cameraButton != null) {
508 hasCamera = true;
509 cameraButton.setOnTouchListener(onTouchListener);
510 cameraButton.setOnClickListener(onClickListener);
511 }
512 if (searchLight != null) {
513 searchLight.setOnClickListener(onClickListener);
514 }
515 }
516 if (hasCamera) {
517 // Warm up KeyguardTouchDelegate so it's ready by the time the camera button is touched.
518 // This will connect to KeyguardService so that touch events are processed.
John Spurlock01534782014-01-13 11:59:22 -0500519 KeyguardTouchDelegate.getInstance(getContext());
Jim Millercaf24fc2013-09-10 18:37:01 -0700520 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400521 }
522
John Spurlockdcf4f212013-05-21 17:19:53 -0400523 public boolean isVertical() {
524 return mVertical;
525 }
526
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400527 public void reorient() {
528 final int rot = mDisplay.getRotation();
529 for (int i=0; i<4; i++) {
530 mRotatedViews[i].setVisibility(View.GONE);
531 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400532 mCurrentView = mRotatedViews[rot];
533 mCurrentView.setVisibility(View.VISIBLE);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400534
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400535 mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
536
Daniel Sandler6da2b762011-09-14 16:04:59 -0400537 // force the low profile & disabled states into compliance
John Spurlocke631b412013-09-18 16:33:57 -0400538 mBarTransitions.init(mVertical);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400539 setDisabledFlags(mDisabledFlags, true /* force */);
Daniel Sandler56598cd2011-09-15 16:02:56 -0400540 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400541
Daniel Sandler60ee2562011-07-22 12:34:33 -0400542 if (DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -0400543 Log.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
Daniel Sandler60ee2562011-07-22 12:34:33 -0400544 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800545
fisherson_lin10e71e02014-01-20 14:47:27 +0800546 // swap to x coordinate if orientation is not in vertical
547 if (mDelegateHelper != null) {
548 mDelegateHelper.setSwapXY(!mVertical);
549 }
550
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800551 setNavigationIconHints(mNavigationIconHints, true);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400552 }
Daniel Sandler48852952011-12-01 14:34:23 -0500553
Daniel Sandler0b69b592012-01-23 21:08:36 -0500554 @Override
Jim Miller960892c2012-05-23 15:50:04 -0700555 protected void onLayout(boolean changed, int l, int t, int r, int b) {
556 super.onLayout(changed, l, t, r, b);
557 mDelegateHelper.setInitialTouchRegion(getHomeButton(), getBackButton(), getRecentsButton());
558 }
559
560 @Override
Daniel Sandler0b69b592012-01-23 21:08:36 -0500561 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
John Spurlockcd686b52013-06-05 10:13:46 -0400562 if (DEBUG) Log.d(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500563 "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400564
565 final boolean newVertical = w > 0 && h > w;
566 if (newVertical != mVertical) {
567 mVertical = newVertical;
John Spurlockcd686b52013-06-05 10:13:46 -0400568 //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400569 reorient();
570 }
571
Daniel Sandler0b69b592012-01-23 21:08:36 -0500572 postCheckForInvalidLayout("sizeChanged");
573 super.onSizeChanged(w, h, oldw, oldh);
574 }
575
576 /*
577 @Override
578 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
John Spurlockcd686b52013-06-05 10:13:46 -0400579 if (DEBUG) Log.d(TAG, String.format(
John Spurlock209bede2013-07-17 12:23:27 -0400580 "onLayout: %s (%d,%d,%d,%d)",
Daniel Sandler0b69b592012-01-23 21:08:36 -0500581 changed?"changed":"notchanged", left, top, right, bottom));
582 super.onLayout(changed, left, top, right, bottom);
583 }
584
585 // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else
586 // fails, any touch on the display will fix the layout.
587 @Override
588 public boolean onInterceptTouchEvent(MotionEvent ev) {
John Spurlockcd686b52013-06-05 10:13:46 -0400589 if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
Daniel Sandler0b69b592012-01-23 21:08:36 -0500590 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
591 postCheckForInvalidLayout("touch");
592 }
593 return super.onInterceptTouchEvent(ev);
594 }
595 */
John Spurlock209bede2013-07-17 12:23:27 -0400596
Daniel Sandler0b69b592012-01-23 21:08:36 -0500597
Daniel Sandler48852952011-12-01 14:34:23 -0500598 private String getResourceName(int resId) {
599 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -0500600 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -0500601 try {
602 return res.getResourceName(resId);
603 } catch (android.content.res.Resources.NotFoundException ex) {
604 return "(unknown)";
605 }
606 } else {
607 return "(null)";
608 }
609 }
610
Daniel Sandler0b69b592012-01-23 21:08:36 -0500611 private void postCheckForInvalidLayout(final String how) {
612 mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget();
613 }
614
Daniel Sandler48852952011-12-01 14:34:23 -0500615 private static String visibilityToString(int vis) {
616 switch (vis) {
617 case View.INVISIBLE:
618 return "INVISIBLE";
619 case View.GONE:
620 return "GONE";
621 default:
622 return "VISIBLE";
623 }
624 }
625
626 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
627 pw.println("NavigationBarView {");
628 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -0700629 final Point size = new Point();
630 mDisplay.getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -0500631
632 pw.println(String.format(" this: " + PhoneStatusBar.viewInfo(this)
633 + " " + visibilityToString(getVisibility())));
634
635 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -0700636 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -0400637 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -0500638 + r.toShortString()
639 + " " + visibilityToString(getWindowVisibility())
640 + (offscreen ? " OFFSCREEN!" : ""));
641
642 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
643 getResourceName(mCurrentView.getId()),
644 mCurrentView.getWidth(), mCurrentView.getHeight(),
645 visibilityToString(mCurrentView.getVisibility())));
646
John Spurlock41c1e352013-09-16 13:57:13 -0400647 pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
Daniel Sandler48852952011-12-01 14:34:23 -0500648 mDisabledFlags,
649 mVertical ? "true" : "false",
Daniel Sandler48852952011-12-01 14:34:23 -0500650 mShowMenu ? "true" : "false"));
651
John Spurlock56d007b2013-10-28 18:40:56 -0400652 dumpButton(pw, "back", getBackButton());
653 dumpButton(pw, "home", getHomeButton());
654 dumpButton(pw, "rcnt", getRecentsButton());
655 dumpButton(pw, "menu", getMenuButton());
656 dumpButton(pw, "srch", getSearchLight());
657 dumpButton(pw, "cmra", getCameraButton());
Daniel Sandler48852952011-12-01 14:34:23 -0500658
Daniel Sandler48852952011-12-01 14:34:23 -0500659 pw.println(" }");
660 }
Jim Millere898ac52012-04-06 17:10:57 -0700661
John Spurlock56d007b2013-10-28 18:40:56 -0400662 private static void dumpButton(PrintWriter pw, String caption, View button) {
663 pw.print(" " + caption + ": ");
664 if (button == null) {
665 pw.print("null");
666 } else {
667 pw.print(PhoneStatusBar.viewInfo(button)
668 + " " + visibilityToString(button.getVisibility())
669 + " alpha=" + button.getAlpha()
670 );
671 if (button instanceof KeyButtonView) {
672 pw.print(" drawingAlpha=" + ((KeyButtonView)button).getDrawingAlpha());
673 pw.print(" quiescentAlpha=" + ((KeyButtonView)button).getQuiescentAlpha());
674 }
675 }
676 pw.println();
677 }
678
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400679}