Android源码笔记--SystemUI

SystemUI

       SystemUI是Android为用户提供系统级别的信息显示与交互的一套UI组件,它包含屏幕顶端的状态栏,底部的导航栏,图片壁纸及RecentPanel(近期使用的APP).SystemUI的表现形式与普通应用类似,也是以一个APK的形式存在于系统之中。其中比较特殊的是状态栏和导航栏的启动方式,它们运行在一个SystemUIService中。现以导航栏的启动方式为例。 如下:

SystemServer.java

static final void startSystemUi(Context context) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
                "com.android.systemui.SystemUIService"));
    //Slog.d(TAG, "Starting service: " + intent);
    context.startServiceAsUser(intent, UserHandle.OWNER);
}
public class SystemUIService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        //获取Application调用startServicesIfNeeded
    }

/*打印堆栈信息*/
    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
        if (args == null || args.length == 0) {
            for (SystemUI ui: services) {
                pw.println("dumping service: " + ui.getClass().getName());
                ui.dump(fd, pw, args);
            }
        } else {
            String svc = args[0];
            for (SystemUI ui: services) {
                String name = ui.getClass().getName();
                if (name.endsWith(svc)) {
                    ui.dump(fd, pw, args);
                }
            }
        }
    }
}

分析:1 是启动SystemUIApplication 2 是打印堆栈信息

SystemUIApplication.java

@Override
public void onCreate() {
    super.onCreate();
    // Set the application theme that is inherited by all services. Note that setting the
    // application theme in the manifest does only work for activities. Keep this in sync with
    // the theme set there.
    setTheme(R.style.systemui_theme);
    //注释广播
    IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
    filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //开启直接返回
            if (mBootCompleted) return;

            if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
            unregisterReceiver(this);
            //标记启动
            mBootCompleted = true;
            //服务是否启动
            if (mServicesStarted) {
                final int N = mServices.length;
                for (int i = 0; i < N; i++) {
                    //回调各服务的onBootCompleted函数
                    mServices[i].onBootCompleted();
                }
            }
        }
    }, filter);
}

分析: 1设置主题  2 注册开机广播,及设置标志位

SystemUIApplication.java

public void startServicesIfNeeded() {
    if (mServicesStarted) {
        return;
    }

    if (!mBootCompleted) {
        // check to see if maybe it was already completed long before we began
        // see ActivityManagerService.finishBooting()
        //获取系统文件中的sys.boot_completed的值
        if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
            mBootCompleted = true;
            if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
        }
    }
    Log.v(TAG, "Starting SystemUI services.");
    final int N = SERVICES.length;
    for (int i=0; i<N; i++) {
        Class<?> cl = SERVICES[i];
        if (DEBUG) Log.d(TAG, "loading: " + cl);
        //实例化各个类实例,放入mServices数组中
        try {
            mServices[i] = (SystemUI)cl.newInstance();
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException ex) {
            throw new RuntimeException(ex);
        }
        mServices[i].mContext = this;
        mServices[i].mComponents = mComponents;
        if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
        mServices[i].start();

        if (mBootCompleted) {
            mServices[i].onBootCompleted();
        }
    }
    //服务启动标志
    mServicesStarted = true;
}

     分析:这个方法中,首先判断mServicesStarted标志为来判断SystemUI相关的服务是否启动,同时根据系统配置文件来检查ActivityManagerService是否finishBooting,然后通过类加载机制来初始化SERVICES数组里面相关的类加入mServices中,然后start。

SystemUIApplication.java

 /**
 * The classes of the stuff to start.
 */
private final Class<?>[] SERVICES = new Class[] {
        com.android.systemui.tuner.TunerService.class,//定制状态栏服务
        com.android.systemui.keyguard.KeyguardViewMediator.class,//锁屏相关
        com.android.systemui.recents.Recents.class,//近期任务
        com.android.systemui.volume.VolumeUI.class,//音量条
        com.android.systemui.statusbar.SystemBars.class,//状态栏
        com.android.systemui.usb.StorageNotification.class,//通知栏
        com.android.systemui.power.PowerUI.class,//电源相关
        com.android.systemui.media.RingtonePlayer.class,//铃声播放相关
};

/**
 * Hold a reference on the stuff we start.
 */
private final SystemUI[] mServices = new SystemUI[SERVICES.length];

     分析:从mServices和SERVICES的定义可以发现SERVICES是一组包含全路径的相关的类,这些类包含一些我们常见的TunerService(定制状态栏服务)、 KeyguardViewMediator(锁屏相关)、Recents(近期任务)、VolumeUI(音量条)、SystemBars(状态栏)、StorageNotification(通知栏)、PowerUI(电源相关)、RingtonePlayer(铃声播放相关)类,它们都是继承与SystemUI抽象类,现在只分析StatusBar相关的SystemBars类。

com.android.systemui.statusbar
SystemBars.java

public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
    private static final String TAG = "SystemBars";
    private static final boolean DEBUG = false;
    private static final int WAIT_FOR_BARS_TO_DIE = 500;

    // manages the implementation coming from the remote process
    private ServiceMonitor mServiceMonitor;

    // in-process fallback implementation, per the product config
    private BaseStatusBar mStatusBar;

    @Override
    public void start() {
        if (DEBUG) Log.d(TAG, "start");
        //实例化ServiceMonitor
        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
        //start
        mServiceMonitor.start();  // will call onNoService if no remote service is found
    }
    /*服务没启动时,ServiceMonitor会回调onNoService*/
    @Override
    public void onNoService() {
        if (DEBUG) Log.d(TAG, "onNoService");
        createStatusBarFromConfig();  // fallback to using an in-process implementation
    }
    /*服务已经启动的回调*/
    @Override
    public long onServiceStartAttempt() {
        if (DEBUG) Log.d(TAG, "onServiceStartAttempt mStatusBar="+mStatusBar);
        if (mStatusBar != null) {
            // tear down the in-process version, we'll recreate it again if needed
            mStatusBar.destroy();
            mStatusBar = null;
            return WAIT_FOR_BARS_TO_DIE;
        }
        return 0;
    }
    /*系统配置改变*/
    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        if (mStatusBar != null) {
            mStatusBar.onConfigurationChanged(newConfig);
        }
    }
    /*打印堆栈*/
    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mStatusBar != null) {
            mStatusBar.dump(fd, pw, args);
        }
    }
    /*从xml文件中获取PhoneStatusBar全路径,通过类加载器实例化类,调用其start*/
    private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        final String clsName = mContext.getString(R.string.config_statusBarComponent);
        if (clsName == null || clsName.length() == 0) {
            throw andLog("No status bar component configured", null);
        }
        Class<?> cls = null;
        try {
            cls = mContext.getClassLoader().loadClass(clsName);
        } catch (Throwable t) {
            throw andLog("Error loading status bar component: " + clsName, t);
        }
        try {
            mStatusBar = (BaseStatusBar) cls.newInstance();
        } catch (Throwable t) {
            throw andLog("Error creating status bar component: " + clsName, t);
        }
        mStatusBar.mContext = mContext;
        mStatusBar.mComponents = mComponents;
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }

    private RuntimeException andLog(String msg, Throwable t) {
        Log.w(TAG, msg, t);
        throw new RuntimeException(msg, t);
    }
}

我们先从start方法开始分析

 @Override
    public void start() {
        if (DEBUG) Log.d(TAG, "start");
        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
        mServiceMonitor.start();  // will call onNoService if no remote service is found
    }

这里实例化ServiceMonitor类start,继续分析ServiceMonitor

ServiceMonitor.java

    ...
    public ServiceMonitor(String ownerTag, boolean debug,
            Context context, String settingKey, Callbacks callbacks) {
        mTag = ownerTag + ".ServiceMonitor";
        mDebug = debug;
        mContext = context;
        mSettingKey = settingKey; // Settings.Secure.BAR_SERVICE_COMPONENT
        mCallbacks = callbacks;
    }

    public void start() {
        // listen for setting changes
        /*Settings.Secure.BAR_SERVICE_COMPONENT改变时回调*/
        ContentResolver cr = mContext.getContentResolver();
        cr.registerContentObserver(Settings.Secure.getUriFor(mSettingKey),
                false /*notifyForDescendents*/, mSettingObserver, UserHandle.USER_ALL);

        // listen for package/component changes
        //应用安装,改变,卸载会触发mBroadcastReceiver广播
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        filter.addDataScheme("package");
        mContext.registerReceiver(mBroadcastReceiver, filter);

        mHandler.sendEmptyMessage(MSG_START_SERVICE);
    }
    ...

     ServiceMOnitor是一个监听Settings.Secure.BAR_SERVICE_COMPONENT是否改变的类,在start中通过监听系统系统时应用的变化来启动服务。

private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String pkg = intent.getData().getSchemeSpecificPart();
        if (mServiceName != null && mServiceName.getPackageName().equals(pkg)) {
            mHandler.sendMessage(mHandler.obtainMessage(MSG_PACKAGE_INTENT, intent));
        }
    }
};

 

ServiceMOnitor.java

应用装载时,通过Handler发送MSG_PACKAGE_INTENT消息事件,我们查看Handler消息回调

    // internal handler + messages used to serialize access to internal state
    public static final int MSG_START_SERVICE = 1; //启动服务,并非真正启动,会根据ServiceName进行判断
    public static final int MSG_CONTINUE_START_SERVICE = 2; //启动服务
    public static final int MSG_STOP_SERVICE = 3;//停止服务消息
    public static final int MSG_PACKAGE_INTENT = 4;//包安装事件消息
    public static final int MSG_CHECK_BOUND = 5;//包改变或者卸载时,重新启动服务消息
    public static final int MSG_SERVICE_DISCONNECTED = 6;//服务断开消息

    private final Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case MSG_START_SERVICE:
                    startService();
                    break;
                case MSG_CONTINUE_START_SERVICE:
                    continueStartService();
                    break;
                case MSG_STOP_SERVICE:
                    stopService();
                    break;
                case MSG_PACKAGE_INTENT:
                    packageIntent((Intent)msg.obj);
                    break;
                case MSG_CHECK_BOUND:
                    checkBound();
                    break;
                case MSG_SERVICE_DISCONNECTED:
                    serviceDisconnected((ComponentName)msg.obj);
                    break;
            }
        }
    };

    private void packageIntent(Intent intent) {
        if (mDebug) Log.d(mTag, "packageIntent intent=" + intent
                + " extras=" + bundleToString(intent.getExtras()));
        if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
            mHandler.sendEmptyMessage(MSG_START_SERVICE);//发送启动服务消息
        } else if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
                || Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
            final PackageManager pm = mContext.getPackageManager();
            final boolean serviceEnabled = isPackageAvailable()
                    && pm.getApplicationEnabledSetting(mServiceName.getPackageName())
                            != PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                    && pm.getComponentEnabledSetting(mServiceName)
                            != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
            if (mBound && !serviceEnabled) {
                stopService();
                scheduleCheckBound();
            } else if (!mBound && serviceEnabled) {
                startService();
            }
        }
    }

分析:当我们SystemUI应用检测到有新应用装载时,会发送MSG_START_SERVICE消息来启动服务,我们接着分析Handler的回调MSG_START_SERVICE消息。

 private void startService() {
        mServiceName = getComponentNameFromSetting();
        if (mDebug) Log.d(mTag, "startService mServiceName=" + mServiceName);
        if (mServiceName == null) {
            mBound = false;
            mCallbacks.onNoService();
        } else {
            long delay = mCallbacks.onServiceStartAttempt();
            mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_START_SERVICE, delay);
        }
    }
    /*从ContentProvider数据库中取得包名*/
    private ComponentName getComponentNameFromSetting() {
        String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                mSettingKey, UserHandle.USER_CURRENT);
        return cn == null ? null : ComponentName.unflattenFromString(cn);
    }

分析:首先从ContentProvider数据库中取得包名,如果没有启动,则回调CallBaback的onNoService服务,否则发送MSG_CONTINUE_START_SERVICE消息启动服务.

private void continueStartService() {
        if (mDebug) Log.d(mTag, "continueStartService");
        Intent intent = new Intent().setComponent(mServiceName);
        try {
            mServiceConnection = new SC();
            mBound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
            if (mDebug) Log.d(mTag, "mBound: " + mBound);
        } catch (Throwable t) {
            Log.w(mTag, "Error binding to service: " + mServiceName, t);
        }
        if (!mBound) {
            mCallbacks.onNoService();
        }
    }

分析:到此可以知道,当远程服务没有启动时,会回调SystemBar的onNoService函数,我们回到SystemBar,分析onNoService函数

...
     @Override
        public void onNoService() {
            if (DEBUG) Log.d(TAG, "onNoService");
            createStatusBarFromConfig();  // fallback to using an in-process implementation
        }
     ...
     private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        final String clsName = mContext.getString(R.string.config_statusBarComponent);//从xml文件读取类名
        if (clsName == null || clsName.length() == 0) {
            throw andLog("No status bar component configured", null);
        }
        //通过类加载器实例化类
        Class<?> cls = null;
        try {
            cls = mContext.getClassLoader().loadClass(clsName);
        } catch (Throwable t) {
            throw andLog("Error loading status bar component: " + clsName, t);
        }
        try {
            mStatusBar = (BaseStatusBar) cls.newInstance();
        } catch (Throwable t) {
            throw andLog("Error creating status bar component: " + clsName, t);
        }
        mStatusBar.mContext = mContext;
        mStatusBar.mComponents = mComponents;
        mStatusBar.start();//调用类的start方法
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }

分析:当远程服务没有启动时,首先从xml文件读取要启动的类名,我们来查看这个xml文件 res\values\config.xml。

res\values\config.xml

    <!-- Component to be used as the status bar service.  Must implement the IStatusBar
     interface.  This name is in the ComponentName flattened format (package/class)  -->
    <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>	

分析:从上面分析得知,当实例化PhoneStatusBar类后会调用start方法,我们就从PhoneStatusBar的start方法开始.


	  @Override
    public void start() {
        //获取WindowManager,初始化当前显示界面大小
        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        updateDisplaySize();
        //src绘图模式
        mScrimSrcModeEnabled = mContext.getResources().getBoolean(
                R.bool.config_status_bar_scrim_behind_use_src);
        //调用父类start方法
        super.start(); // calls createAndAddWindows()
        //MediaSession相关
        mMediaSessionManager
                = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
        // TODO: use MediaSessionManager.SessionListener to hook us up to future updates
        // in session state
        //添加导航栏
        addNavigationBar();

        // Lastly, call to the icon policy to install/update all the icons.
        //更新状态栏图标
        mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController,
                mUserInfoController, mBluetoothController);
        mIconPolicy.setCurrentUserSetup(mUserSetup);
        mSettingsObserver.onChange(false); // set up

        mHeadsUpObserver.onChange(true); // set up
        if (ENABLE_HEADS_UP) {
            mContext.getContentResolver().registerContentObserver(
                    Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true,
                    mHeadsUpObserver);
            mContext.getContentResolver().registerContentObserver(
                    Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
                    mHeadsUpObserver);
        }
        mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
        mUnlockMethodCache.addListener(this);
        //锁屏
        startKeyguard();

        mDozeServiceHost = new DozeServiceHost();
        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mDozeServiceHost);
        putComponent(DozeHost.class, mDozeServiceHost);
        putComponent(PhoneStatusBar.class, this);

        /// M:add for multi window @{
        if(MultiWindowProxy.isSupported()) {
            registerMWProxyAgain();
        }
        /// @}
        setControllerUsers();

        notifyUserAboutHiddenNotifications();

        mScreenPinningRequest = new ScreenPinningRequest(mContext);
    }
    ...

接着分析PhoneStatusBar父类的BaseStatusBar的start方法

public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
        RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger,
        NotificationData.Environment {	
	
	public void start() {
    	Log.d(TAG, "[*zxDebug*] BaseStatusBar start()");
        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
        mDisplay = mWindowManager.getDefaultDisplay();
        mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
                Context.DEVICE_POLICY_SERVICE);

        mNotificationColorUtil = NotificationColorUtil.getInstance(mContext);

        mNotificationData = new NotificationData(this);

        mAccessibilityManager = (AccessibilityManager)
                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);

        mDreamManager = IDreamManager.Stub.asInterface(
                ServiceManager.checkService(DreamService.DREAM_SERVICE));
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
     
	 mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

        mRecents = getComponent(RecentsComponent.class);
        mRecents.setCallback(this);

        final Configuration currentConfig = mContext.getResources().getConfiguration();
	
	
	 StatusBarIconList iconList = new StatusBarIconList();
        mCommandQueue = new CommandQueue(this, iconList);

        int[] switches = new int[8];
        ArrayList<IBinder> binders = new ArrayList<IBinder>();
        try {
            mBarService.registerStatusBar(mCommandQueue, iconList, switches, binders);
        } catch (RemoteException ex) {
            // If the system process isn't there we're doomed anyway.
        }
        
        Log.d(TAG, "[*zxDebug*] BaseStatusBar start() begin createAndAddWindows");
        createAndAddWindows();
        Log.d(TAG, "[*zxDebug*] BaseStatusBar start() over createAndAddWindows");

        disable(switches[0], false /* animate */);
        setSystemUiVisibility(switches[1], 0xffffffff);
        topAppWindowChanged(switches[2] != 0);
        // StatusBarManagerService has a back up of IME token and it's restored here.
        setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0);

			...
			}
			}

分析:BaseStatusBar关于StatusBar相关的最主要是调用了createAndAddWindows方法,我们看下这个方法的定义

 /**
     * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
     * and add them to the window manager.
     */
    protected abstract void createAndAddWindows();

     分析:这是一个抽象方法,也就是说,它会回调到子类的createAndAddWindows的实现方法中,我们重新回到PhoneStatusBar中,找到createAndAddWindows的方法实现

	@Override
    public void createAndAddWindows() {
        addStatusBarWindow();
    }

    private void addStatusBarWindow() {
        makeStatusBarView();//创建statusbar视图
        mStatusBarWindowManager = new StatusBarWindowManager(mContext);
        //通过StatusBarWindowManager类的add方法加载到Window窗体中
        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
    }
    ...
    protected PhoneStatusBarView makeStatusBarView() {
        final Context context = mContext;
        //通过Resources更新显示大小和一些资源文件
        Resources res = context.getResources();

        updateDisplaySize(); // populates mDisplayMetrics
        updateResources();
        //加载StartBarWindowView视图
        mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
                R.layout.super_status_bar, null);
        mStatusBarWindow.setService(this);
        //监听下拉事件
        mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                checkUserAutohide(v, event);
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    if (mExpandedVisible) {
                        animateCollapsePanels();
                    }
                }
                return mStatusBarWindow.onTouchEvent(event);
            }
        });
        //状态栏
        mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
        mStatusBarView.setBar(this);
        //
        PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
        mStatusBarView.setPanelHolder(holder);
        //通知栏
        mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
                R.id.notification_panel);
        mNotificationPanel.setStatusBar(this);

        //  M: setBackground in 512 low ram device
        if (!ActivityManager.isHighEndGfx() && !FeatureOptions.LOW_RAM_SUPPORT) {
            mStatusBarWindow.setBackground(null);
            mNotificationPanel.setBackground(new FastColorDrawable(context.getColor(
                    R.color.notification_panel_solid_background)));
        }
  try {
            //是否显示导航栏
            boolean showNav = mWindowManagerService.hasNavigationBar();
             Log.v(TAG, "hasNavigationBar=" + showNav);
            if (showNav) {
                /// M: add for multi window @{
                //加载导航栏布局
                int layoutId = R.layout.navigation_bar;
                if(MultiWindowProxy.isSupported()) {
                    layoutId = R.layout.navigation_bar_float_window;
                }
                mNavigationBarView = (NavigationBarView) View.inflate(context,
                        /*R.layout.navigation_bar*/layoutId, null);
                /// @}

                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);

        // figure out which pixel-format to use for the status bar.
        mPixelFormat = PixelFormat.OPAQUE;
	
	.....

       分析:关键部分是在判断导航栏是否显示那一块。由mWindowManagerService的hasNavigationBar来决定是否显示导航栏,同时通过加载navigation_bar(多窗口加载navigation_bar_float_window)布局来显示导航栏,我们来查看hasNavigationBar方法,因为mWidnwoManagerService是IWindowManagerService由PhoneWindowManager进行调用: 

frameworks\base\service\core\java\com\android\server\PhoneWindowManager.java
	
PhoneWindowManager

    ...
    // 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;
    }
    ...
    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;
    }
    ...	
	
	
	
	
从framework\base\core\res\res\valuse\config.xml中获取mHashNavigationBar的值

    <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
         autodetected from the Configuration. -->
    <bool name="config_showNavigationBar">ture</bool>	

分析:这里给我们提供一个方法去控制导航栏是否显示。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值