zoukankan      html  css  js  c++  java
  • android(cm11)状态栏源代码分析(一)

    (一):写在前面

    近期因为工作须要,须要了解CM11中的有关于StatusBar相关的内容。总的来说,刚開始阅读其源代码的时候,是有点困难,只是通过构建相关代码的脑图和流程图,几天下来。我已经对其源代码有了一个大体的了解。只是其内部细节还有非常多不是非常明确,可是这对于我的工作来说就已经足够了。

    在android系统中,有关于系统状态栏有关的代码位于/framework/base/packages/SystemUI/中,非常明显,该SystemUI是一个app源代码。当系统进行编译的时候,就会生成SystemUI.apk。

    所以我们对待它就像是对待普通app程序一样。

    好了。如今開始我们的代码分析。

    (二):StatusBar流程分析

    对于android系统来说,SystemUI的启动是有位于packages以下的android系统launcher启动器启动的,启动方式事实上是通过java的反射机制实现的。其启动SystemUI的SystemUIService。该SystemUIService是Service的一个子类,同一时候,在该类中通过反射机制同一时候启动6个和系统UI相关的类,这个我们后面再分析。

    这6个和系统UI相关的类都继承自SystemUI类,在SystemUIService中实例化这6个类的时候同一时候启动该类相应的start()方法来启动服务。而他们的start()函数中主要是启动相关ServiceMonitor的start方法,在该ServiceMonitor中主要是启动相关的包的服务。即调用startService()函数。

    在启动服务的时候,就会实例化StatusBar,而且调用其onStart()函数。这个就是StatusBar的启动流程,这样说的话可能理解起来比較繁琐,以下的这张图就是系统状态栏的启动过程的流程图:

    这里写图片描写叙述

    (三):SystemUIService源代码分析

    以下我们来分析一下SystemUIService的源代码。

    该SystemUIService类继承自Service类。说明该类是一个服务类,在该类中都是干了什么工作呢?我们先找到Service类中的onCreate()方法:

    public void onCreate() {
            HashMap<Class<?

    >, Object> components = new HashMap<Class<?>, Object>(); final int N = SERVICES.length; for (int i=0; i<N; i++) { Class<?

    > cl = SERVICES[i]; Log.d(TAG, "loading: " + cl); 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 = components; Log.d(TAG, "running: " + mServices[i]); mServices[i].start(); } }

    从这里能够看出,通过一个for循环将数组SERVICES中保存的类实例化,即调用newInstance()函数。实例化完毕之后。对其对象中的属性进行赋值,最后再调用相应的start()函数。

    以下我们来看一下SERVICES数组中的保存的6个类:

     private final Class<?>[] SERVICES = new Class[] {
                com.android.systemui.recent.Recents.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,
                com.android.systemui.settings.SettingsUI.class,
            };
    

    当然,在这个类里面也存有其它相关的函数。包含配置发生改变的函数,销毁函数等,以下我们来看一下该类的脑图:

    这里写图片描写叙述

    因为在这里启动了6个相关的类。可是我们在这篇文章中,我们先分析SystemBars.class类。

    (四):SystemBars源代码分析

    在上面的流程图中,我们知道,启动的6个类都是继承自SystemUI类,我们先来看一下SystemUI类:

    SystemUI类是一个抽象类。在该类中定义了一些方法,当中包含启动方法,配置发生改变的函数。销毁函数等。

    以下我们先来看一下该类的代码:

     public Context mContext;
        public Map<Class<?>, Object> mComponents;
    
        public abstract void start();
    
        protected void onConfigurationChanged(Configuration newConfig) {
        }
    
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        }
    
        @SuppressWarnings("unchecked")
        public <T> T getComponent(Class<T> interfaceType) {
            return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
        }
    
        public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
            if (mComponents != null) {
                mComponents.put(interfaceType, component);
            }
        }
    

    在这个类中,比較有意思的就是Map对象,该对象就是保存相关类的组件。以下我们来看一下脑图:

    这里写图片描写叙述

    以下我们来看SystemBars的源代码。在这里我们主要查看的是其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类的对象来说,其start()函数,终于都要调用位于SystemBars类中的createStatusBarFromConfig()函数,在该函数中。主要是调用BaseStatusBar对象的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()); }

    以下我们来看一下SystemBars类的脑图:

    这里写图片描写叙述

    (五):ServiceMonitor源代码分析

    在ServiceMonitor类中主要是使用Handler中的信息类来进行包服务管理。当中有启动服务,继续服务,暂停服务,停止服务等函数,在这里辗转反側终于还是回归到SystemBars中的StatusBars的启动:

    这里写图片描写叙述

    (六):终于流程分析

    上面我们提到了,终于还是要启动StatusBar,而这里启动的StatusBar并非其真正的StatusBar,而是他的子类,也就是位于com/android/systemui/statusbar/phone/PhoneStatusBar.java,以下我们来看一下他的start()函数:

    @Override
        public void start() {
            mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                    .getDefaultDisplay();
            updateDisplaySize();
    
            ThemeConfig currentTheme = mContext.getResources().getConfiguration().themeConfig;
            if (currentTheme != null) {
                mCurrentTheme = (ThemeConfig)currentTheme.clone();
            } else {
                mCurrentTheme = ThemeConfig.getSystemTheme();
            }
    
            mLocationController = new LocationController(mContext);
            mBatteryController = new BatteryController(mContext);
            mDockBatteryController = new DockBatteryController(mContext);
            mBluetoothController = new BluetoothController(mContext);
    
            super.start(); // calls createAndAddWindows()
    
            addNavigationBar();
    
            SettingsObserver observer = new SettingsObserver(mHandler);
            observer.observe();
    
            // Developer options - Force Navigation bar
            try {
                boolean needsNav = mWindowManagerService.needsNavigationBar();
                if (!needsNav) {
                    mDevForceNavbarObserver = new DevForceNavbarObserver(mHandler);
                    mDevForceNavbarObserver.observe();
                }
            } catch (RemoteException ex) {
                // no window manager?

    good luck with that } // Lastly, call to the icon policy to install/update all the icons. mIconPolicy = new PhoneStatusBarPolicy(mContext); mHeadsUpObserver.onChange(true); // set up if (ENABLE_HEADS_UP) { mContext.getContentResolver().registerContentObserver( Settings.System.getUriFor(Settings.System.HEADS_UP_NOTIFICATION), true, mHeadsUpObserver, mCurrentUserId); } }

    在这个代码中。我们看到代码中,有一个类PhoneStatusBarPolicy类,该类就是向状态栏中加入图标的管理类。以下我们来看一下该类的构造方法:

        public PhoneStatusBarPolicy(Context context) {
            mContext = context;
            mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
    
            // listen for broadcasts
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_ALARM_CHANGED);
            filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
            filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
            filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
            filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
            filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
            filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
            mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
    
            int numPhones = MSimTelephonyManager.getDefault().getPhoneCount();
            mSimState = new IccCardConstants.State[numPhones];
            for (int i=0; i < numPhones; i++) {
                mSimState[i] = IccCardConstants.State.READY;
            }
    
            // TTY status
            mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);
            mService.setIconVisibility("tty", false);
    
            // Cdma Roaming Indicator, ERI
            mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);
            mService.setIconVisibility("cdma_eri", false);
    
            // bluetooth status
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
            int bluetoothIcon = R.drawable.stat_sys_data_bluetooth;
            if (adapter != null) {
                mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
                if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
                    bluetoothIcon = R.drawable.stat_sys_data_bluetooth_connected;
                }
            }
            mService.setIcon("bluetooth", bluetoothIcon, 0, null);
            mService.setIconVisibility("bluetooth", mBluetoothEnabled);
    
            // Alarm clock
            mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
            mService.setIconVisibility("alarm_clock", false);
    
            // Sync state
            mService.setIcon("sync_active", R.drawable.stat_sys_sync, 0, null);
            mService.setIconVisibility("sync_active", false);
            // "sync_failing" is obsolete: b/1297963
    
            // volume
            mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
            mService.setIconVisibility("volume", false);
            updateVolume();
        }

    而这里主要是加入监听广播,而且加入其它相关图标。

    还有有些图标是在布局文件里加入的,当中于StatusBar相关的布局文件是在以下几个文件里的:

    • SystemUI/res/layout/status_bar.xml
    • SystemUI/res/layout/super_status_bar.xml

    以及其内部include的相关文件。

    好了,至此,有关与android系统状态栏相关的代码已经了解的差点儿相同了,通过这个,我们能够向状态栏中加入图标或者是删除图标。这个是比較简单了。

    好了。有关与状态栏的代码我们就分析到此。后面我们再来分析QuickSettings的相关的代码。

  • 相关阅读:
    飘逸的python
    hdu 4512 吉哥系列故事——完美队形I(最长公共上升自序加强版)
    Codeforces 482B. Interesting Array 线段树
    《开源框架那些事儿21》:巧借力与借巧力
    openNebula libvirt-virsh attach disk device for kvm
    configure mount nfs
    opennebula kvm attach disk
    openNebula 运维系列虚拟机virtual machines operations
    yum subversion puppet puppet-server
    文件系统,快存储,对象存储
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7243415.html
Copyright © 2011-2022 走看看