android5.1_SystemUI启动流程

1、概要

     对于Phone来说SystemUI指的是:StatusBar(状态栏)、NavigationBar(导航栏)、Keyguard(锁屏)等等。
启动后Phone界面上的信号,蓝牙标志,Wifi标志等等这些状态显示标志都会在StatusBar上显示。当我们的设备开机后,首先需要给用户呈现的就是各种界面同时也包括了我们的SystemUI,因此对于整个Android系统来说,SystemUI都有举足轻重的作用。

本篇主要解析SystemUI中StatusBar的代码流程。


2、SystemUI截图

贴几张垃圾图,供新人更好的了解SystemUI

android5.1_SystemUI启动流程_第1张图片android5.1_SystemUI启动流程_第2张图片android5.1_SystemUI启动流程_第3张图片




3、SystemUI的大致启动流程图(网上找的,与最新的处理流程并没有太大出入)



android5.1_SystemUI启动流程_第4张图片



4、SystemUI启动流程代码解析

4.1、启动SystemUIService

SystemServer.java

   

AndroidManifest.xml中可以看到SystemUIService,

        <service android:name="SystemUIService"

            android:exported="true"

            />

 

上面的SystemUIService是在SystemServer中启动的

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

    }

 

 

4.2启动相应的服务

 

SystemUIService.java

 

SystemUIService中的onCreate()方法中调用了SystemUIApplication的startServicesIfNeeded()方法.

    public void onCreate() {

        super.onCreate();

        ((SystemUIApplication) getApplication()).startServicesIfNeeded();

}

 

而在SystemUIApplication中,首先把需要启动的services添加到一个数组中

 

    private final Class[] SERVICES = new Class[] {

            com.android.systemui.keyguard.KeyguardViewMediator.class,

            com.android.systemui.recent.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

    };

 

然后实例化一个对象:

private final SystemUI[] mServices = new SystemUI[SERVICES.length];

 

然后正式启动需要的服务:

public void startServicesIfNeeded() {

        .....

        Log.v(TAG, "Starting SystemUI services.");

        final int N = SERVICES.length;

        for (int i=0; i

            Class cl = SERVICES[i];

            if (DEBUG) Log.d(TAG, "loading: " + cl);

            try {

                mServices[i] = (SystemUI)cl.newInstance();

            } 

........

            mServices[i].mContext = this;

            mServices[i].mComponents = mComponents;

            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);

            mServices[i].start();

......

    }

 

 

 

4.3、启动SystemBar

 

SystemBars.java

 

 

已com.android.systemui.statusbar.SystemBars.class为例:

public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {

   @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.java

 

    public void start() {

        // listen for setting changes

        ContentResolver cr = mContext.getContentResolver();

        cr.registerContentObserver(Settings.Secure.getUriFor(mSettingKey),

                false /*notifyForDescendents*/, mSettingObserver,  UserHandle.USER_ALL);

 

        // listen for package/component changes

        IntentFilter filter = new IntentFilter();

        filter.addAction(Intent.ACTION_PACKAGE_ADDED);

        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);

        filter.addDataScheme("package");

        mContext.registerReceiver(mBroadcastReceiver, filter);

        mHandler.sendEmptyMessage(MSG_START_SERVICE);

}

 

 

主线程接受消息后调用startService启动服务.

private final Handler mHandler = new Handler() {

        public void handleMessage(Message msg) {

            switch(msg.what) {

                case MSG_START_SERVICE:

                    startService();

                    break;

 

 

 

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

        }

}

 

 

    private ComponentName getComponentNameFromSetting() {

        String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),

                mSettingKey, UserHandle.USER_CURRENT);

        return cn == null ? null : ComponentName.unflattenFromString(cn);

    }

 

 

SystemBars.java

 

    @Override

    public void onNoService() {

        if (DEBUG) Log.d(TAG, "onNoService");

        createStatusBarFromConfig();  // fallback to using an in-process implementation

    }

 

 

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

        } .....

        try {

            mStatusBar = (BaseStatusBar) cls.newInstance();

        } ....

        mStatusBar.mContext = mContext;

        mStatusBar.mComponents = mComponents;

//这里是调用的BaseStatusBar的start()方法,当有子类继承时,直接调用

        mStatusBar.start();

    }

 

 

PhoneBar.java

 

@Override

public void start() {

mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))

                .getDefaultDisplay();

    updateDisplaySize();

    mScrimSrcModeEnabled = mContext.getResources().getBoolean(

                R.bool.config_status_bar_scrim_behind_use_src);

//PhoneBar继承了BaseStatusBar,所以也需要重写基类的方法,同时调用基类的start()

    super.start(); // calls createAndAddWindows()

 

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

    mSettingsObserver.onChange(false); // set up

    mHeadsUpObserver.onChange(true); // set up      

   }

 

 

BaseStatusBar.java

 

public void start() {

     ........

        mBarService = IStatusBarService.Stub.asInterface(

                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

.......

        // Connect in to the status bar manager service

        StatusBarIconList iconList = new StatusBarIconList();

        mCommandQueue = new CommandQueue(this, iconList);

 

        int[] switches = new int[8];

        ArrayList binders = new ArrayList();

        try {

            mBarService.registerStatusBar(mCommandQueue, iconList, switches, binders);

        } 

        createAndAddWindows();

......

        // Set up the initial icon state

        int N = iconList.size();

        int viewIndex = 0;

        for (int i=0; i

            StatusBarIcon icon = iconList.getIcon(i);

            if (icon != null) {

                addIcon(iconList.getSlot(i), i, viewIndex, icon);

                viewIndex++;

            }

        }

.........

    }

 

 

BaseStatusBar.java这里的createAndAddWindowsaddIcon等的实现是在BaseStatusBar的子类中,以PhoneStatusBar.java为例:

 

public void createAndAddWindows() {

        addStatusBarWindow();

}

 

 private void addStatusBarWindow() {

        makeStatusBarView();

        mStatusBarWindowManager = new StatusBarWindowManager(mContext);

        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());

    }

 

 

 

 

protected PhoneStatusBarView makeStatusBarView() {

  .......

//定义StatusBarWindow

        mStatusBarWindow = (StatusBarWindowView) View.inflate(context,

                R.layout.super_status_bar, null);

        mStatusBarWindow.mService = 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);

            }});

 

 

//定义StatusBarView

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

 

........

//定义expanded status bar

        mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);

        mShowCarrierInPanel = (mCarrierLabel != null);

 

.........

        return mStatusBarView;

    }

 

 

前面提到,在BaseStatusBar.start()中调用addIcon去加载icon,其实现也在PhoneStatusBar.java中。

 

public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {

//初始化StatusBarIconView 

        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);

        view.set(icon);//加载icon

//将设置好icon的StatusBarIconView加载到mStatusIcons布局中

        mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(

                LayoutParams.WRAP_CONTENT, mIconSize));

        view = new StatusBarIconView(mContext, slot, null);

        view.set(icon);

        mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(

                LayoutParams.WRAP_CONTENT, mIconSize));

    }

 

通过查看StatusBarIconView的继承关系我们可以发现public class StatusBarIconView extends AnimatedImageView ,继续跟踪可以看到public class AnimatedImageView extends ImageView,也就是说我们的StatusBarIconView其实就是一个封装过的ImageView,这样自然能够盛放我们的Icons.

 

 

PhoneStatusBarPolicy.java

 

在前面的PhoneStatusBar.start()开始icon加载:

 

// Lastly, call to the icon policy to install/update all the icons.

    mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController,  mHotspotController);

从PhoneStatusBarPolicy的构造参数中,可以看到:

public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot) {

    mContext = context;

    mCast = cast;

    mHotspot = hotspot;

    mService =(StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);

 

        // listen for broadcasts

        IntentFilter filter = new IntentFilter();

        filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);

        filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);

        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);

        filter.addAction(AudioManager.INTERNAL_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(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);

        filter.addAction(Intent.ACTION_USER_SWITCHED);

        // SPRD: fixbug421569 ADD headset icon in statusbar

        filter.addAction(Intent.ACTION_HEADSET_PLUG);

        mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);

 

        // TTY status

        mService.setIcon(SLOT_TTY,  R.drawable.stat_sys_tty_mode, 0, null);

        mService.setIconVisibility(SLOT_TTY, false);

.........  

}

 

对象mService属于StatusBarManager的实例,所以会进入StatusBarManager类:

 

StatusBarManager.java

    public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {

        try {

            final IStatusBarService svc = getService();

            if (svc != null) {

                svc.setIcon(slot, mContext.getPackageName(), iconId, iconLevel,

                    contentDescription);

            }

        } catch (RemoteException ex) {

            // system process is dead anyway.

            throw new RuntimeException(ex);

        }

    }

 

 

StatusBarManagerService.java

 

public class StatusBarManagerService extends IStatusBarService.Stub {

    private volatile IStatusBar mBar;

    private StatusBarIconList mIcons = new StatusBarIconList();

 public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,

            String contentDescription) {

        enforceStatusBar();

        synchronized (mIcons) {

        int index = mIcons.getSlotIndex(slot);

        StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,

                    iconLevel, 0,contentDescription);

            mIcons.setIcon(index, icon);

            if (mBar != null) {

                try {

                    mBar.setIcon(index, icon);

                } catch (RemoteException ex) {

                }

            }

        }

}

 

 

StatusBarIconList.java

 

public void setIcon(int index, StatusBarIcon icon) {

          mIcons[index] = icon.clone();

}

 

 

CommandQueue.java

 

public class CommandQueue extends IStatusBar.Stub {

private StatusBarIconList mList;

private Callbacks mCallbacks;

private Handler mHandler = new H();

... 

    public void setIcon(int index, StatusBarIcon icon) {

        synchronized (mList) {

            int what = MSG_ICON | index;

            mHandler.removeMessages(what);

            mHandler.obtainMessage(what, OP_SET_ICON, 0, icon.clone()).sendToTarget();

        }

 }

}

 

 

private final class H extends Handler {

    public void handleMessage(Message msg) {

    final int what = msg.what & MSG_MASK;

    switch (what) {

         case MSG_ICON: {

            final int index = msg.what & INDEX_MASK;

            final int viewIndex = mList.getViewIndex(index);

            switch (msg.arg1) {

                 case OP_SET_ICON: {

                   StatusBarIcon icon = (StatusBarIcon)msg.obj;

                   StatusBarIcon old = mList.getIcon(index);

                    if (old == null) {

                       mList.setIcon(index, icon);

                       mCallbacks.addIcon(mList.getSlot(index), index, viewIndex, icon);

                     } else {

                  List.setIcon(index, icon);

                  mCallbacks.updateIcon(mList.getSlot(index), index, viewIndex,old, icon);

                      }

                    break;

                }

 

 

接下来又是回到BaseStatusBar.java中,接着回到PhoneStatusBar中执行addIcon():

 

public abstract class BaseStatusBar extends SystemUI implements CommandQueue{

 

public class PhoneStatusBar extends BaseStatusBar implements DemoMode{

 

public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {

        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);

        view.set(icon);

        mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(

                LayoutParams.WRAP_CONTENT, mIconSize));

        view = new StatusBarIconView(mContext, slot, null);

        view.set(icon);

        mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(

                LayoutParams.WRAP_CONTENT, mIconSize));

}

 

最后,将图标添加至状态栏上.

 

补充:

 

StatusBarManagerService.java

 

    public StatusBarManagerService(Context context, WindowManagerService windowManager) {

        mContext = context;

        mWindowManager = windowManager;

//这里加载了系统预置的所有icon,路径在:./frameworks/base/core/res/res/values/config.xml  

        final Resources res = context.getResources();  mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons));

 

        LocalServices.addService(StatusBarManagerInternal.class, mInternalService);

}

 

 

StatusBarManagerService是在SystemServer中启动的.

    if (!disableSystemUI) {

        try {

          Slog.i(TAG, "Status Bar");

          statusBar = new StatusBarManagerService(context, wm);

          ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);

       } catch (Throwable e) {

            reportWtf("starting StatusBarManagerService", e);

          }

      }

 

以上是详细的对SystemUI 中的最重要的 StatusBar代码流程分析。


6、相关资源位置

代码位置:/frameworks/base/packages/SystemUI



初出江湖,希望各路大神&&前辈多多指点,晚辈拜谢~~~

你可能感兴趣的:(android源码解析)