android SystemUi学习笔记

SystemUI 是如何启动的

systemui包括了系统栏和导航栏,也就是我们看到的电量、时间栏和返回按键这类的导航栏。systemui也是一个apk,所以我们就会想他是如何启动的呢,
android 系统的启动肯定是首先 systemserver, systemserver会启动android 系统所需的各种服务,比如activtymanagerservice,当mActivityManagerService的systemReady回调后就会执行 启动systemui的动作。

ActivityManagerService 的systemReady

    public void systemReady(final Runnable goingCallback) {
        synchronized(this) {
            if (mSystemReady) {
                // If we're done calling all the receivers, run the next "boot phase" passed in
                // by the SystemServer
                if (goingCallback != null) {
                    goingCallback.run();
                }
                return;
            }

            mLocalDeviceIdleController
                    = LocalServices.getService(DeviceIdleController.LocalService.class);

            // Make sure we have the current profile info, since it is needed for
            // security checks.
            updateCurrentProfileIdsLocked();

            mRecentTasks.clear();
            mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
            mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
            mTaskPersister.startPersisting();

            // Check to see if there are any update receivers to run.
            if (!mDidUpdate) {
                if (mWaitingUpdate) {
                    return;
                }
                final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
                mWaitingUpdate = deliverPreBootCompleted(new Runnable() {
                    public void run() {
                        synchronized (ActivityManagerService.this) {
                            mDidUpdate = true;
                        }
                        showBootMessage(mContext.getText(
                                R.string.android_upgrading_complete),
                                false);
                        writeLastDonePreBootReceivers(doneReceivers);
                       systemReady(goingCallback); //这里调到了调到了 SystemServer 里面设置的回调。启动systemui 
                    }
                }, doneReceivers, UserHandle.USER_OWNER);

                if (mWaitingUpdate) {
                    return;
                }
                mDidUpdate = true;
            }

            mAppOpsService.systemReady();
            mSystemReady = true;
        }

        ArrayList<ProcessRecord> procsToKill = null;
        synchronized(mPidsSelfLocked) {
            for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
                ProcessRecord proc = mPidsSelfLocked.valueAt(i);
                if (!isAllowedWhileBooting(proc.info)){
                    if (procsToKill == null) {
                        procsToKill = new ArrayList<ProcessRecord>();
                    }
                    procsToKill.add(proc);
                }
            }
        }

        synchronized(this) {
            if (procsToKill != null) {
                for (int i=procsToKill.size()-1; i>=0; i--) {
                    ProcessRecord proc = procsToKill.get(i);
                    Slog.i(TAG, "Removing system update proc: " + proc);
                    removeProcessLocked(proc, true, false, "system update done");
                }
            }

            // Now that we have cleaned up any update processes, we
            // are ready to start launching real processes and know that
            // we won't trample on them any more.
            mProcessesReady = true;
        }

        Slog.i(TAG, "System now ready");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
            SystemClock.uptimeMillis());

        synchronized(this) {
            // Make sure we have no pre-ready processes sitting around.

            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                ResolveInfo ri = mContext.getPackageManager()
                        .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
                                STOCK_PM_FLAGS);
                CharSequence errorMsg = null;
                if (ri != null) {
                    ActivityInfo ai = ri.activityInfo;
                    ApplicationInfo app = ai.applicationInfo;
                    if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
                        mTopAction = Intent.ACTION_FACTORY_TEST;
                        mTopData = null;
                        mTopComponent = new ComponentName(app.packageName,
                                ai.name);
                    } else {
                        errorMsg = mContext.getResources().getText(
                                com.android.internal.R.string.factorytest_not_system);
                    }
                } else {
                    errorMsg = mContext.getResources().getText(
                            com.android.internal.R.string.factorytest_no_action);
                }
                if (errorMsg != null) {
                    mTopAction = null;
                    mTopData = null;
                    mTopComponent = null;
                    Message msg = Message.obtain();
                    msg.what = SHOW_FACTORY_ERROR_MSG;
                    msg.getData().putCharSequence("msg", errorMsg);
                    mUiHandler.sendMessage(msg);
                }
            }
        }

        retrieveSettings();
        loadResourcesOnSystemReady();

        synchronized (this) {
            readGrantedUriPermissionsLocked();
        }

        if (goingCallback != null) goingCallback.run();

        mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
                Integer.toString(mCurrentUserId), mCurrentUserId);
        mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
                Integer.toString(mCurrentUserId), mCurrentUserId);
        mSystemServiceManager.startUser(mCurrentUserId);

        synchronized (this) {
            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                try {
                    List apps = AppGlobals.getPackageManager().
                        getPersistentApplications(STOCK_PM_FLAGS);
                    if (apps != null) {
                        int N = apps.size();
                        int i;
                        for (i=0; i<N; i++) {
                            ApplicationInfo info
                                = (ApplicationInfo)apps.get(i);
                            if (info != null &&
                                    !info.packageName.equals("android")) {
                                addAppLocked(info, false, null /* ABI override */);
                            }
                        }
                    }
                } catch (RemoteException ex) {
                    // pm is in same process, this will never happen.
                }
            }

            // Start up initial activity.
            mBooting = true;
            startHomeActivityLocked(mCurrentUserId, "systemReady"); //这里启动launcher 应用,所以 systemui 是在launcher之前启动

            try {
                if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
                    Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
                            + " data partition or your device will be unstable.");
                    mUiHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
                }
            } catch (RemoteException e) {
            }

            if (!Build.isBuildConsistent()) {
                Slog.e(TAG, "Build fingerprint is not consistent, warning user");
                mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
            }

            long ident = Binder.clearCallingIdentity();
            try {
                Intent intent = new Intent(Intent.ACTION_USER_STARTED);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_FOREGROUND);
                intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
                broadcastIntentLocked(null, null, intent,
                        null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                        null, false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
                intent = new Intent(Intent.ACTION_USER_STARTING);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
                broadcastIntentLocked(null, null, intent,
                        null, new IIntentReceiver.Stub() {
                            @Override
                            public void performReceive(Intent intent, int resultCode, String data,
                                    Bundle extras, boolean ordered, boolean sticky, int sendingUser)
                                    throws RemoteException {
                            }
                        }, 0, null, null,
                        new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
                        null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
            } catch (Throwable t) {
                Slog.wtf(TAG, "Failed sending first user broadcasts", t);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
            mStackSupervisor.resumeTopActivitiesLocked();
            sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
        }
    }

SystemServer 当中

// These are needed to propagate to the runnable below.
        final NetworkManagementService networkManagementF = networkManagement;
        final NetworkStatsService networkStatsF = networkStats;
        final NetworkPolicyManagerService networkPolicyF = networkPolicy;
        final ConnectivityService connectivityF = connectivity;
        final NetworkScoreService networkScoreF = networkScore;
        final WallpaperManagerService wallpaperF = wallpaper;
        final InputMethodManagerService immF = imm;
        final LocationManagerService locationF = location;
        final CountryDetectorService countryDetectorF = countryDetector;
        final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
        final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService;
        final TextServicesManagerService textServiceManagerServiceF = tsms;
        final StatusBarManagerService statusBarF = statusBar;
        final AssetAtlasService atlasF = atlas;
        final InputManagerService inputManagerF = inputManager;
        final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
        final MediaRouterService mediaRouterF = mediaRouter;
        final AudioService audioServiceF = audioService;
        final MmsServiceBroker mmsServiceF = mmsService;

        // We now tell the activity manager it is okay to run third party
        // code.  It will call back into us once it has gotten to the state
        // where third party code can really run (but before it has actually
        // started launching the initial applications), for us to complete our
        // initialization.
        mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                Slog.i(TAG, "Making services ready");
                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_ACTIVITY_MANAGER_READY);

                try {
                    mActivityManagerService.startObservingNativeCrashes();
                } catch (Throwable e) {
                    reportWtf("observing native crashes", e);
                }

                Slog.i(TAG, "WebViewFactory preparation");
                WebViewFactory.prepareWebViewInSystemServer();

                try {
                    startSystemUi(context); //启动SystemUi
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }
                try {
                    if (networkScoreF != null) networkScoreF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Score Service ready", e);
                }
                try {
                    if (networkManagementF != null) networkManagementF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Managment Service ready", e);
                }
                try {
                    if (networkStatsF != null) networkStatsF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Stats Service ready", e);
                }
                try {
                    if (networkPolicyF != null) networkPolicyF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Policy Service ready", e);
                }
                try {
                    if (connectivityF != null) connectivityF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Connectivity Service ready", e);
                }
                try {
                    if (audioServiceF != null) audioServiceF.systemReady();
                } catch (Throwable e) {
                    reportWtf("Notifying AudioService running", e);
                }
                Watchdog.getInstance().start();

                // It is now okay to let the various system services start their
                // third party code...
                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);

                try {
                    if (wallpaperF != null) wallpaperF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying WallpaperService running", e);
                }
                try {
                    if (immF != null) immF.systemRunning(statusBarF);
                } catch (Throwable e) {
                    reportWtf("Notifying InputMethodService running", e);
                }
                try {
                    if (locationF != null) locationF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying Location Service running", e);
                }
                try {
                    if (countryDetectorF != null) countryDetectorF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying CountryDetectorService running", e);
                }
                try {
                    if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying NetworkTimeService running", e);
                }
                try {
                    if (commonTimeMgmtServiceF != null) {
                        commonTimeMgmtServiceF.systemRunning();
                    }
                } catch (Throwable e) {
                    reportWtf("Notifying CommonTimeManagementService running", e);
                }
                try {
                    if (textServiceManagerServiceF != null)
                        textServiceManagerServiceF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying TextServicesManagerService running", e);
                }
                try {
                    if (atlasF != null) atlasF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying AssetAtlasService running", e);
                }
                try {
                    // TODO(BT) Pass parameter to input manager
                    if (inputManagerF != null) inputManagerF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying InputManagerService running", e);
                }
                try {
                    if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying TelephonyRegistry running", e);
                }
                try {
                    if (mediaRouterF != null) mediaRouterF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying MediaRouterService running", e);
                }

                try {
                    if (mmsServiceF != null) mmsServiceF.systemRunning();
                } catch (Throwable e) {
                    reportWtf("Notifying MmsService running", e);
                }
            }
        });
    }
//启动了 systemui package里面的SystemUIService
 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);
    }```

###  systemui 中运行了哪些服务?
直接看看 systemuiservice里面代码

package com.android.systemui;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import java.io.FileDescriptor;
import java.io.PrintWriter;

public class SystemUIService extends Service {

@Override
public void onCreate() {
    super.onCreate();
    ((SystemUIApplication) getApplication()).startServicesIfNeeded(); // 只是做了这件事情
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

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

}


走到了 SystemUIApplication 里面

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,
};

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

    if (!mBootCompleted) {
        // check to see if maybe it was already completed long before we began
        // see ActivityManagerService.finishBooting()
        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);
        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;
}
以上看以看出分别启动了  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,
这些子服务,它自己启动没有干什么事情。

### systemui的那些ui布局是在哪里被显示出来的 ?
带着这个问题 看看com.android.systemui.statusbar.SystemBars.class 这个的实现,
SystemBars.java 中启动

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  的start

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.addAction(Intent.ACTION_PACKAGE_REMOVED);
    filter.addDataScheme("package");
    mContext.registerReceiver(mBroadcastReceiver, filter)

    mHandler.sendEmptyMessage(MSG_START_SERVICE);
}
上面注册了一个setting数据库的监听器和package change的广播,然而这个不是我们现在关心的,看到最后 mHandler有发送一个消息出去MSG_START_SERVICE。又启动了一个服务?继续看吧

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

public interface Callbacks {
/** The service does not exist or failed to bind /
void onNoService();
/
* The service is about to start, this is a chance to perform cleanup and
* delay the start if necessary */
long onServiceStartAttempt();
}

可见 Callbacks  这个回调是在实现的地方来执行的,实现了它的地方在SystemBars.java

@Override
public void onNoService() {
if (DEBUG) Log.d(TAG, "onNoService");
//这里开始创建statusbar了
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;
}

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

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

下面就要正在把view相关的内容添加进来了BaseStatusBar 的start()
public void 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);

    mContext.getContentResolver().registerContentObserver(
            Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
            mSettingsObserver);
    mContext.getContentResolver().registerContentObserver(
            Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
            mSettingsObserver);
    mContext.getContentResolver().registerContentObserver(
            Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
            mSettingsObserver,
            UserHandle.USER_ALL);

    mContext.getContentResolver().registerContentObserver(
            Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
            true,
            mLockscreenSettingsObserver,
            UserHandle.USER_ALL);

    mBarService = IStatusBarService.Stub.asInterface(
            ServiceManager.getService(Context.STATUS_BAR_SERVICE));

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

    final Configuration currentConfig = mContext.getResources().getConfiguration();
    mLocale = currentConfig.locale;
    mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
    mFontScale = currentConfig.fontScale;

    mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);

    mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,
            android.R.interpolator.linear_out_slow_in);
    mFastOutLinearIn = AnimationUtils.loadInterpolator(mContext,
            android.R.interpolator.fast_out_linear_in);

    // Connect in to the status bar manager service
    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.
    }

    createAndAddWindows();//创建view 

    mSettingsObserver.onChange(false); // set up
    disable(switches[0], switches[6], 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);

    // Set up the initial icon state
    int N = iconList.size();
    int viewIndex = 0;
    for (int i=0; i<N; i++) {
        StatusBarIcon icon = iconList.getIcon(i);
        if (icon != null) {
            addIcon(iconList.getSlot(i), i, viewIndex, icon);
            viewIndex++;
        }
    }

    // Set up the initial notification state.
    try {
        mNotificationListener.registerAsSystemService(mContext,
                new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
                UserHandle.USER_ALL);
    } catch (RemoteException e) {
        Log.e(TAG, "Unable to register notification listener", e);
    }


    if (DEBUG) {
        Log.d(TAG, String.format(
                "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
               iconList.size(),
               switches[0],
               switches[1],
               switches[2],
               switches[3]
               ));
    }

    mCurrentUserId = ActivityManager.getCurrentUser();
    setHeadsUpUser(mCurrentUserId);

    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_USER_SWITCHED);
    filter.addAction(Intent.ACTION_USER_ADDED);
    filter.addAction(Intent.ACTION_USER_PRESENT);
    filter.addAction(BANNER_ACTION_CANCEL);
    filter.addAction(BANNER_ACTION_SETUP);
    mContext.registerReceiver(mBroadcastReceiver, filter);

    IntentFilter allUsersFilter = new IntentFilter();
    allUsersFilter.addAction(
            DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
            null, null);
    updateCurrentProfilesCache();
}
可以从源码中看到     protected abstract void createAndAddWindows(); 是一个抽象方法,所以这个应该是由它的子类来进行实现的,PhoneStatusBar.java 中找到了它的实现。

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

private void addStatusBarWindow() {
    makeStatusBarView();// 加载view
    mStatusBarWindowManager = new StatusBarWindowManager(mContext);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}


// ================================================================================
// Constructing the view
// ================================================================================
protected PhoneStatusBarView makeStatusBarView() {
    final Context context = mContext;

    Resources res = context.getResources();

    updateDisplaySize(); // populates mDisplayMetrics
    updateResources();

    mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
            R.layout.super_status_bar, null); // view的布局文件
    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);

    if (!ActivityManager.isHighEndGfx()) {
        mStatusBarWindow.setBackground(null);
        mNotificationPanel.setBackground(new FastColorDrawable(context.getColor(
                R.color.notification_panel_solid_background)));
    }

    mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow);
    mHeadsUpManager.setBar(this);
    mHeadsUpManager.addListener(this);
    mHeadsUpManager.addListener(mNotificationPanel);
    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();
        if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
        if (showNav) {
            mNavigationBarView =
                (NavigationBarView) View.inflate(context, R.layout.navigation_bar, 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;

    mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
            R.id.notification_stack_scroller);
    mStackScroller.setLongPressListener(getNotificationLongClicker());
    mStackScroller.setPhoneStatusBar(this);
    mStackScroller.setGroupManager(mGroupManager);
    mStackScroller.setHeadsUpManager(mHeadsUpManager);
    mGroupManager.setOnGroupChangeListener(mStackScroller);

    mKeyguardIconOverflowContainer =
            (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
                    R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
    mKeyguardIconOverflowContainer.setOnActivatedListener(this);
    mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
    mStackScroller.setOverflowContainer(mKeyguardIconOverflowContainer);

    SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate(
                    R.layout.status_bar_notification_speed_bump, mStackScroller, false);
    mStackScroller.setSpeedBumpView(speedBump);
    mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
            R.layout.status_bar_no_notifications, mStackScroller, false);
    mStackScroller.setEmptyShadeView(mEmptyShadeView);
    mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
            R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
    mDismissView.setOnButtonClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES);
            clearAllNotifications();
        }
    });
    mStackScroller.setDismissView(mDismissView);
    mExpandedContents = mStackScroller;

    mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);
    mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
    mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);

    ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
    ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
    View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
    mScrimController = new ScrimController(scrimBehind, scrimInFront, headsUpScrim,
            mScrimSrcModeEnabled);
    mHeadsUpManager.addListener(mScrimController);
    mStackScroller.setScrimController(mScrimController);
    mScrimController.setBackDropView(mBackdrop);
    mStatusBarView.setScrimController(mScrimController);
    mDozeScrimController = new DozeScrimController(mScrimController, context);

    mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
    mHeader.setActivityStarter(this);
    mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
    mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
    mKeyguardBottomArea =
            (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
    mKeyguardBottomArea.setActivityStarter(this);
    mKeyguardBottomArea.setAssistManager(mAssistManager);
    mKeyguardIndicationController = new KeyguardIndicationController(mContext,
            (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
                    R.id.keyguard_indication_text));
    mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);

    // set the inital view visibility
    setAreThereNotifications();

    mIconController = new StatusBarIconController(
            mContext, mStatusBarView, mKeyguardStatusBar, this);

    // Background thread for any controllers that need it.
    mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
    mHandlerThread.start();

    // Other icons
    mLocationController = new LocationControllerImpl(mContext,
            mHandlerThread.getLooper()); // will post a notification
    mBatteryController = new BatteryController(mContext);
    mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
        @Override
        public void onPowerSaveChanged() {
            mHandler.post(mCheckBarModes);
            if (mDozeServiceHost != null) {
                mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
            }
        }
        @Override
        public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
            // noop
        }
    });
    mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
    mHotspotController = new HotspotControllerImpl(mContext);
    mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());
    mSecurityController = new SecurityControllerImpl(mContext);
    if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
        mRotationLockController = new RotationLockControllerImpl(mContext);
    }
    mUserInfoController = new UserInfoController(mContext);
    mVolumeComponent = getComponent(VolumeComponent.class);
    if (mVolumeComponent != null) {
        mZenModeController = mVolumeComponent.getZenController();
    }
    mCastController = new CastControllerImpl(mContext);
    final SignalClusterView signalCluster =
            (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
    final SignalClusterView signalClusterKeyguard =
            (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
    final SignalClusterView signalClusterQs =
            (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
    mNetworkController.addSignalCallback(signalCluster);
    mNetworkController.addSignalCallback(signalClusterKeyguard);
    mNetworkController.addSignalCallback(signalClusterQs);
    signalCluster.setSecurityController(mSecurityController);
    signalCluster.setNetworkController(mNetworkController);
    signalClusterKeyguard.setSecurityController(mSecurityController);
    signalClusterKeyguard.setNetworkController(mNetworkController);
    signalClusterQs.setSecurityController(mSecurityController);
    signalClusterQs.setNetworkController(mNetworkController);
    final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
    if (isAPhone) {
        mNetworkController.addEmergencyListener(mHeader);
    }

    mFlashlightController = new FlashlightController(mContext);
    mKeyguardBottomArea.setFlashlightController(mFlashlightController);
    mKeyguardBottomArea.setPhoneStatusBar(this);
    mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
    mAccessibilityController = new AccessibilityController(mContext);
    mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
    mNextAlarmController = new NextAlarmController(mContext);
    mKeyguardMonitor = new KeyguardMonitor(mContext);
    if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {
        mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
                mHandler);
    }
    mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
            (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),
            mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController);


    // Set up the quick settings tile panel
    mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
    if (mQSPanel != null) {
        final QSTileHost qsh = new QSTileHost(mContext, this,
                mBluetoothController, mLocationController, mRotationLockController,
                mNetworkController, mZenModeController, mHotspotController,
                mCastController, mFlashlightController,
                mUserSwitcherController, mKeyguardMonitor,
                mSecurityController);
        mQSPanel.setHost(qsh);
        mQSPanel.setTiles(qsh.getTiles());
        mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
        mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
        mHeader.setQSPanel(mQSPanel);
        qsh.setCallback(new QSTileHost.Callback() {
            @Override
            public void onTilesChanged() {
                mQSPanel.setTiles(qsh.getTiles());
            }
        });
    }

    // User info. Trigger first load.
    mHeader.setUserInfoController(mUserInfoController);
    mKeyguardStatusBar.setUserInfoController(mUserInfoController);
    mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController);
    mUserInfoController.reloadUserInfo();

    mHeader.setBatteryController(mBatteryController);
    ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
            mBatteryController);
    mKeyguardStatusBar.setBatteryController(mBatteryController);
    mHeader.setNextAlarmController(mNextAlarmController);

    PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    mBroadcastReceiver.onReceive(mContext,
            new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));


    // receive broadcasts
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    filter.addAction(Intent.ACTION_SCREEN_ON);
    context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);

    IntentFilter demoFilter = new IntentFilter();
    if (DEBUG_MEDIA_FAKE_ARTWORK) {
        demoFilter.addAction(ACTION_FAKE_ARTWORK);
    }
    demoFilter.addAction(ACTION_DEMO);
    context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
            android.Manifest.permission.DUMP, null);

    // listen for USER_SETUP_COMPLETE setting (per-user)
    resetUserSetupObserver();

    // disable profiling bars, since they overlap and clutter the output on app windows
    ThreadedRenderer.overrideProperty("disableProfileBars", "true");

    // Private API call to make the shadows look better for Recents
    ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));

    return mStatusBarView;
}
![状态栏控件树的结构](http://upload-images.jianshu.io/upload_images/2043394-ddde815f8966729f?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 142,811评论 1 300
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 61,236评论 1 256
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 94,386评论 0 212
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 41,004评论 0 175
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 48,779评论 1 255
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 38,776评论 1 176
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 30,393评论 2 271
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,161评论 0 166
  • 想象着我的养父在大火中拼命挣扎,窒息,最后皮肤化为焦炭。我心中就已经是抑制不住地欢快,这就叫做以其人之道,还治其人...
    爱写小说的胖达阅读 28,979评论 6 229
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 32,511评论 0 213
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,296评论 2 215
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 30,637评论 1 229
  • 白月光回国,霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前, 不然我有一百种方法让你生不如死。]我...
    爱写小说的胖达阅读 24,242评论 0 31
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,121评论 2 213
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 31,512评论 3 204
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,619评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,013评论 0 167
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 33,525评论 2 230
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 33,615评论 2 231

推荐阅读更多精彩内容