赞
踩
1.三个虚拟键的显示初始化是在Frameworks下的SystemUI中。
/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
- // ================================================================================
- // Constructing the view
- // ================================================================================
- protected PhoneStatusBarView makeStatusBarView() {
- final Context context = mContext;
- Resources res = context.getResources();
-
- ......
- mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
- mNotificationData.setHeadsUpManager(mHeadsUpManager);
-
- if (MULTIUSER_DEBUG) {
- mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
- R.id.header_debug_info);
- mNotificationPanelDebugText.setVisibility(View.VISIBLE);
- }
-
- try {
- boolean showNav = mWindowManagerService.hasNavigationBar();//控制Navigationbar中是否显示3个虚拟按键
- if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
- if (showNav) {
- mNavigationBarView =
- (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);//本布局中定义了3个虚拟键
-
- mNavigationBarView.setDisabledFlags(mDisabled1);
- mNavigationBarView.setBar(this);
- mNavigationBarView.setOnVerticalChangedListener(
- new NavigationBarView.OnVerticalChangedListener() {
- @Override
- public void onVerticalChanged(boolean isVertical) {
- if (mAssistManager != null) {
- mAssistManager.onConfigurationChanged();
- }
- mNotificationPanel.setQsScrimEnabled(!isVertical);
- }
- });
- mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- checkUserAutohide(v, event);
- return false;
- }});
- }
- } catch (RemoteException ex) {
- // no window manager? good luck with that
- }
-
- mAssistManager = new AssistManager(this, context);

2.由以上代码可知,3个虚拟键的显示与否取决于showNav,而这又取决于mWindowManagerService和它的方法hasNavigationBar()返回的值。而mWindowManagerService并非再本类中声明,而是从其父类中继承而来,并在父类中初始化。
/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
- public abstract class BaseStatusBar extends SystemUI implements
- CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
- RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger,
- NotificationData.Environment {
- public static final String TAG = "StatusBar";
- public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final boolean MULTIUSER_DEBUG = false;
- ......
-
- private UserManager mUserManager;
-
- // UI-specific methods
-
- /**
- * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
- * and add them to the window manager.
- */
- protected abstract void createAndAddWindows();
-
- protected WindowManager mWindowManager;
- protected IWindowManager mWindowManagerService;

mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
3.在WindowManagerGlobal中获取IWindowManager实例。
/frameworks/base/core/java/android/view/WindowManagerGlobal.java
- public static IWindowManager getWindowManagerService() {
- synchronized (WindowManagerGlobal.class) {
- if (sWindowManagerService == null) {
- sWindowManagerService = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));//
- try {
- sWindowManagerService = getWindowManagerService();
- ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
- }
- }
- return sWindowManagerService;
- }
- }
4.上面的sWindowManagerService也是IWindowManager声明的,可以看出上面方法中,sWindowManagerService递归从IWindowManager.Stub中获取实例。我们来看看IWindowManager中的声明。
/frameworks/base/core/java/android/view/IWindowManager.aidl
- /**
- * System private interface to the window manager.
- *
- * {@hide}
- */
- interface IWindowManager
- {
- /**
- * ===== NOTICE =====
- * The first three methods must remain the first three methods. Scripts
- * and tools rely on their transaction number to work properly.
- */
- // This is used for debugging
- boolean startViewServer(int port); // Transaction #1
- boolean stopViewServer(); // Transaction #2
- boolean isViewServerRunning(); // Transaction #3
-
- ......
-
- /**
- * Device has a software navigation bar (separate from the status bar).
- */
- boolean hasNavigationBar();
- ......
- }

5.回归到PhoneStatusBar中调用的hasNavigationBar()方法,正是IWindowManager接口中的,至于如何返回值怎么来决定,还得取决于实现此接口的方法实现。
6.经过查找,有两个类实现了IWindowManager接口,分别为IWindowManagerImpl和WindowManagerService,先看IWindowManagerImpl类。
/frameworks/base/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
- public class IWindowManagerImpl implements IWindowManager {
-
- private final Configuration mConfig;
- private final DisplayMetrics mMetrics;
- private final int mRotation;
- private final boolean mHasNavigationBar;
-
- public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation,
- boolean hasNavigationBar) {
- mConfig = config;
- mMetrics = metrics;
- mRotation = rotation;
- mHasNavigationBar = hasNavigationBar;//在IWindowManagerImpl初始化时传入
- }
-
- // custom API.
-
- public DisplayMetrics getMetrics() {
- return mMetrics;
- }
-
- // ---- implementation of IWindowManager that we care about ----
-
- @Override
- public int getRotation() throws RemoteException {
- return mRotation;
- }
-
- @Override
- public boolean hasNavigationBar() {
- return mHasNavigationBar;//直接返回类属性
- }
- ......
- }

7.IWindowManagerImpl先看到这里,再看一下WindowManagerService类,它是个隐藏类,不对上层应用开放。
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
- /** {@hide} */
- public class WindowManagerService extends IWindowManager.Stub
- implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
- static final String TAG = "WindowManager";
- /// M: Enable/Disable WMS log
- static boolean DEBUG = false;
- static boolean DEBUG_ADD_REMOVE = false;
- ......
-
- final WindowManagerPolicy mPolicy = MtkPhoneWindowUtility.makeNewWindowManager();//MTK
- //final WindowManagerPolicy mPolicy = new PhoneWindowManager();//QCOM
- @Override
- public boolean hasNavigationBar() {
- return mPolicy.hasNavigationBar();
- }
- ......
- }

8.从上方可以看出,最终使用的是PhoneWindowManager中实现的hasNavigationBar方法。而PhoneWindowManager实现了WindowManagerPolicy接口中的方法。
/local/sdb/talkback/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
- package com.android.server.policy;
-
- /**
- * WindowManagerPolicy implementation for the Android phone UI. This
- * introduces a new method suffix, Lp, for an internal lock of the
- * PhoneWindowManager. This is used to protect some internal state, and
- * can be acquired with either the Lw and Li lock held, so has the restrictions
- * of both of those when held.
- */
- public class PhoneWindowManager implements WindowManagerPolicy {
- static final String TAG = "WindowManager";
- /// M: runtime switch debug flags @{
- static boolean DEBUG = false;
- ......
-
- boolean mHasNavigationBar = false;
-
- @Override
- public void setInitialDisplaySize(Display display, int width, int height, int density) {
- // This method might be called before the policy has been fully initialized
- // or for other displays we don't care about.
- if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
- return;
- }
- mDisplay = display;
-
- ......
-
- // SystemUI (status bar) layout policy
- int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
- int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
-
- // Allow the navigation bar to move on non-square small devices (phones).
- mNavigationBarCanMove = width != height && shortSizeDp < 600;
-
- mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);//首先给予一个默认值
- // Allow a system property to override this. Used by the emulator.
- // See also hasNavigationBar().
- String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");//通过读取系统属性来覆盖默认值,厂家可以很容易通过定制系统属性来控制虚拟键显示与否
- if ("1".equals(navBarOverride)) {
- mHasNavigationBar = false;
- } else if ("0".equals(navBarOverride)) {
- mHasNavigationBar = true;
- }
-
- // For demo purposes, allow the rotation of the HDMI display to be controlled.
- // By default, HDMI locks rotation to landscape.
- if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
- mDemoHdmiRotation = mPortraitRotation;
- } else {
- mDemoHdmiRotation = mLandscapeRotation;
- }
- mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
-
- // For demo purposes, allow the rotation of the remote display to be controlled.
- // By default, remote display locks rotation to landscape.
- if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
- mDemoRotation = mPortraitRotation;
- } else {
- mDemoRotation = mLandscapeRotation;
- }
- mDemoRotationLock = SystemProperties.getBoolean(
- "persist.demo.rotationlock", false);
-
- // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
- // http://developer.android.com/guide/practices/screens_support.html#range
- mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
- res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
- // For debug purposes the next line turns this feature off with:
- // $ adb shell setprop config.override_forced_orient true
- // $ adb shell wm size reset
- !"true".equals(SystemProperties.get("config.override_forced_orient"));
- }
-
- // Use this instead of checking config_showNavigationBar so that it can be consistently
- // overridden by qemu.hw.mainkeys in the emulator.
- @Override
- public boolean hasNavigationBar() {
- return mHasNavigationBar;//返回的boolean值
- }
- ......
- }

9.如此,需要跟踪系统属性从那里来。经过查询,该系统属性是编译时加入。
/device/{XXXX}/{Project_name}/system.prop
- # temporary enables NAV bar (soft keys)
- qemu.hw.mainkeys=0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。