当前位置:   article > 正文

[Android][SystemUI]navigationbar 3个虚拟键隐藏与显示_安卓虚拟三大键

安卓虚拟三大键

源码流程追踪

1.三个虚拟键的显示初始化是在Frameworks下的SystemUI中。

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

  1. // ================================================================================
  2. // Constructing the view
  3. // ================================================================================
  4. protected PhoneStatusBarView makeStatusBarView() {
  5. final Context context = mContext;
  6. Resources res = context.getResources();
  7. ......
  8. mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
  9. mNotificationData.setHeadsUpManager(mHeadsUpManager);
  10. if (MULTIUSER_DEBUG) {
  11. mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
  12. R.id.header_debug_info);
  13. mNotificationPanelDebugText.setVisibility(View.VISIBLE);
  14. }
  15. try {
  16. boolean showNav = mWindowManagerService.hasNavigationBar();//控制Navigationbar中是否显示3个虚拟按键
  17. if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
  18. if (showNav) {
  19. mNavigationBarView =
  20. (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);//本布局中定义了3个虚拟键
  21. mNavigationBarView.setDisabledFlags(mDisabled1);
  22. mNavigationBarView.setBar(this);
  23. mNavigationBarView.setOnVerticalChangedListener(
  24. new NavigationBarView.OnVerticalChangedListener() {
  25. @Override
  26. public void onVerticalChanged(boolean isVertical) {
  27. if (mAssistManager != null) {
  28. mAssistManager.onConfigurationChanged();
  29. }
  30. mNotificationPanel.setQsScrimEnabled(!isVertical);
  31. }
  32. });
  33. mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
  34. @Override
  35. public boolean onTouch(View v, MotionEvent event) {
  36. checkUserAutohide(v, event);
  37. return false;
  38. }});
  39. }
  40. } catch (RemoteException ex) {
  41. // no window manager? good luck with that
  42. }
  43. mAssistManager = new AssistManager(this, context);

2.由以上代码可知,3个虚拟键的显示与否取决于showNav,而这又取决于mWindowManagerService和它的方法hasNavigationBar()返回的值。而mWindowManagerService并非再本类中声明,而是从其父类中继承而来,并在父类中初始化。

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

  1. public abstract class BaseStatusBar extends SystemUI implements
  2. CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
  3. RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger,
  4. NotificationData.Environment {
  5. public static final String TAG = "StatusBar";
  6. public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
  7. public static final boolean MULTIUSER_DEBUG = false;
  8. ......
  9. private UserManager mUserManager;
  10. // UI-specific methods
  11. /**
  12. * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
  13. * and add them to the window manager.
  14. */
  15. protected abstract void createAndAddWindows();
  16. protected WindowManager mWindowManager;
  17. protected IWindowManager mWindowManagerService;

mWindowManagerService = WindowManagerGlobal.getWindowManagerService();

3.在WindowManagerGlobal中获取IWindowManager实例。

/frameworks/base/core/java/android/view/WindowManagerGlobal.java

  1. public static IWindowManager getWindowManagerService() {
  2. synchronized (WindowManagerGlobal.class) {
  3. if (sWindowManagerService == null) {
  4. sWindowManagerService = IWindowManager.Stub.asInterface(
  5. ServiceManager.getService("window"));//
  6. try {
  7. sWindowManagerService = getWindowManagerService();
  8. ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
  9. } catch (RemoteException e) {
  10. Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
  11. }
  12. }
  13. return sWindowManagerService;
  14. }
  15. }

4.上面的sWindowManagerService也是IWindowManager声明的,可以看出上面方法中,sWindowManagerService递归从IWindowManager.Stub中获取实例。我们来看看IWindowManager中的声明。

/frameworks/base/core/java/android/view/IWindowManager.aidl

  1. /**
  2. * System private interface to the window manager.
  3. *
  4. * {@hide}
  5. */
  6. interface IWindowManager
  7. {
  8. /**
  9. * ===== NOTICE =====
  10. * The first three methods must remain the first three methods. Scripts
  11. * and tools rely on their transaction number to work properly.
  12. */
  13. // This is used for debugging
  14. boolean startViewServer(int port); // Transaction #1
  15. boolean stopViewServer(); // Transaction #2
  16. boolean isViewServerRunning(); // Transaction #3
  17. ......
  18. /**
  19. * Device has a software navigation bar (separate from the status bar).
  20. */
  21. boolean hasNavigationBar();
  22. ......
  23. }

5.回归到PhoneStatusBar中调用的hasNavigationBar()方法,正是IWindowManager接口中的,至于如何返回值怎么来决定,还得取决于实现此接口的方法实现。

6.经过查找,有两个类实现了IWindowManager接口,分别为IWindowManagerImpl和WindowManagerService,先看IWindowManagerImpl类。

/frameworks/base/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java

  1. public class IWindowManagerImpl implements IWindowManager {
  2. private final Configuration mConfig;
  3. private final DisplayMetrics mMetrics;
  4. private final int mRotation;
  5. private final boolean mHasNavigationBar;
  6. public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation,
  7. boolean hasNavigationBar) {
  8. mConfig = config;
  9. mMetrics = metrics;
  10. mRotation = rotation;
  11. mHasNavigationBar = hasNavigationBar;//在IWindowManagerImpl初始化时传入
  12. }
  13. // custom API.
  14. public DisplayMetrics getMetrics() {
  15. return mMetrics;
  16. }
  17. // ---- implementation of IWindowManager that we care about ----
  18. @Override
  19. public int getRotation() throws RemoteException {
  20. return mRotation;
  21. }
  22. @Override
  23. public boolean hasNavigationBar() {
  24. return mHasNavigationBar;//直接返回类属性
  25. }
  26. ......
  27. }

7.IWindowManagerImpl先看到这里,再看一下WindowManagerService类,它是个隐藏类,不对上层应用开放。

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

  1. /** {@hide} */
  2. public class WindowManagerService extends IWindowManager.Stub
  3. implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
  4. static final String TAG = "WindowManager";
  5. /// M: Enable/Disable WMS log
  6. static boolean DEBUG = false;
  7. static boolean DEBUG_ADD_REMOVE = false;
  8. ......
  9. final WindowManagerPolicy mPolicy = MtkPhoneWindowUtility.makeNewWindowManager();//MTK
  10. //final WindowManagerPolicy mPolicy = new PhoneWindowManager();//QCOM
  11. @Override
  12. public boolean hasNavigationBar() {
  13. return mPolicy.hasNavigationBar();
  14. }
  15. ......
  16. }

8.从上方可以看出,最终使用的是PhoneWindowManager中实现的hasNavigationBar方法。而PhoneWindowManager实现了WindowManagerPolicy接口中的方法。

/local/sdb/talkback/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

  1. package com.android.server.policy;
  2. /**
  3. * WindowManagerPolicy implementation for the Android phone UI. This
  4. * introduces a new method suffix, Lp, for an internal lock of the
  5. * PhoneWindowManager. This is used to protect some internal state, and
  6. * can be acquired with either the Lw and Li lock held, so has the restrictions
  7. * of both of those when held.
  8. */
  9. public class PhoneWindowManager implements WindowManagerPolicy {
  10. static final String TAG = "WindowManager";
  11. /// M: runtime switch debug flags @{
  12. static boolean DEBUG = false;
  13. ......
  14. boolean mHasNavigationBar = false;
  15. @Override
  16. public void setInitialDisplaySize(Display display, int width, int height, int density) {
  17. // This method might be called before the policy has been fully initialized
  18. // or for other displays we don't care about.
  19. if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
  20. return;
  21. }
  22. mDisplay = display;
  23. ......
  24. // SystemUI (status bar) layout policy
  25. int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
  26. int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
  27. // Allow the navigation bar to move on non-square small devices (phones).
  28. mNavigationBarCanMove = width != height && shortSizeDp < 600;
  29. mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);//首先给予一个默认值
  30. // Allow a system property to override this. Used by the emulator.
  31. // See also hasNavigationBar().
  32. String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");//通过读取系统属性来覆盖默认值,厂家可以很容易通过定制系统属性来控制虚拟键显示与否
  33. if ("1".equals(navBarOverride)) {
  34. mHasNavigationBar = false;
  35. } else if ("0".equals(navBarOverride)) {
  36. mHasNavigationBar = true;
  37. }
  38. // For demo purposes, allow the rotation of the HDMI display to be controlled.
  39. // By default, HDMI locks rotation to landscape.
  40. if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
  41. mDemoHdmiRotation = mPortraitRotation;
  42. } else {
  43. mDemoHdmiRotation = mLandscapeRotation;
  44. }
  45. mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
  46. // For demo purposes, allow the rotation of the remote display to be controlled.
  47. // By default, remote display locks rotation to landscape.
  48. if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
  49. mDemoRotation = mPortraitRotation;
  50. } else {
  51. mDemoRotation = mLandscapeRotation;
  52. }
  53. mDemoRotationLock = SystemProperties.getBoolean(
  54. "persist.demo.rotationlock", false);
  55. // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
  56. // http://developer.android.com/guide/practices/screens_support.html#range
  57. mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
  58. res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
  59. // For debug purposes the next line turns this feature off with:
  60. // $ adb shell setprop config.override_forced_orient true
  61. // $ adb shell wm size reset
  62. !"true".equals(SystemProperties.get("config.override_forced_orient"));
  63. }
  64. // Use this instead of checking config_showNavigationBar so that it can be consistently
  65. // overridden by qemu.hw.mainkeys in the emulator.
  66. @Override
  67. public boolean hasNavigationBar() {
  68. return mHasNavigationBar;//返回的boolean值
  69. }
  70. ......
  71. }

9.如此,需要跟踪系统属性从那里来。经过查询,该系统属性是编译时加入。

/device/{XXXX}/{Project_name}/system.prop

  1. # temporary enables NAV bar (soft keys)
  2. qemu.hw.mainkeys=0

涉及类关联

经过流程跟踪,大致涉及的类关联如下:



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/219285
推荐阅读
相关标签
  

闽ICP备14008679号