1.下拉通知栏简介
2.源码位置
SystemUIService.java
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
SystemUIApplication.java
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
SystemBars.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
config_statusBarComponent
frameworks/base/packages/SystemUI/res/values/config.xml
ServiceMonitor.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
PhoneStatusBar.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
BaseStatusBar.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
PhoneStatusBarView.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
super_status_bar.xml
frameworks/base/packages/SystemUI/res/layout/super_status_bar.xml
status_bar.xml
frameworks/base/packages/SystemUI/res/layout/status_bar.xml
system_icons.xml
frameworks/base/packages/SystemUI/res/layout/system_icons.xml
signal_cluster_view.xml
frameworks/base/packages/SystemUI/res/layout/signal_cluster_view.xml
3. Status Bar启动流程
1. 当系统BOOT_COMPLETED后,SystemUIService会由SystemServer启动;之后 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,
};
2. SystemBars启动后经由ServiceMonitor后, 启动config.xm中配置的StatusBar类。
com.android.systemui.statusbar.phone.PhoneStatusBar
3. 通过PhoneStatusBar和父类BaseStatusBar的start()方法,最终makeStatusBarView()被调用。
protected PhoneStatusBarView makeStatusBarView() {
// 加载StatusBarWindowView视图,该视图包括Status bar/Quick Settings/Notification Panel
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
mStatusBarWindow.setService(this);
// 监听OnTouch事件,当下拉时展开Notification Panel
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);
}
});
// 获取Status bar视图
mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
mStatusBarView.setBar(this);
// 将Status bar视图传递给StatusBarIconController
mIconController = new StatusBarIconController(
mContext, mStatusBarView, mKeyguardStatusBar, this);
// Other icons
// 电量控制类
mBatteryController = new BatteryController(mContext);
// 网络控制类
mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
// 安全控制类
mSecurityController = new SecurityControllerImpl(mContext);
// 信号簇视图,包括VPN/WIFI/手机信号等
final SignalClusterView signalCluster =
(SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
// 绑定网络控制器
mNetworkController.addSignalCallback(signalCluster);
// 绑定完全控制器
signalCluster.setSecurityController(mSecurityController);
// 绑定网络控制器
signalCluster.setNetworkController(mNetworkController);
// 绑定电量控制器
((BatteryMeterView) mStatusBarView.findViewById(R.id.battery))
.setBatteryController(mBatteryController);
// Set up the quick settings tile panel
AutoReinflateContainer container = (AutoReinflateContainer) mStatusBarWindow.findViewById(R.id.qs_auto_reinflate_container);
//下拉通知栏总区域
if (container != null) {
final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
mBluetoothController, //蓝牙
mLocationController, //地址
mRotationLockController,//自动旋转
mNetworkController, //数据开关
mZenModeController, //勿扰模式
mHotspotController, //热点
mCastController, //投射
mFlashlightController,//手电筒
mUserSwitcherController, // 不显示
mUserInfoController, // 不显示
mKeyguardMonitor, // 不显示
mSecurityController, // 不显示
mBatteryController, // 电池管理
mIconController, // 不显示
mNextAlarmController,// 不显示
mHotKnotController, // 热点
mRingController, //铃声模式
mNfcController //NFC
);
mBrightnessMirrorController
= new BrightnessMirrorController(mStatusBarWindow);
container.addInflateListener(new InflateListener() {
@Override
public void onInflated(View v) {
QSContainer qsContainer = (QSContainer) v.findViewById(
R.id.quick_settings_container);//qs_panel.xml
qsContainer.setHost(qsh);
mQSPanel = qsContainer.getQsPanel();//QSPanel:下拉第一阶段快捷键显示条
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
mKeyguardStatusBar.setQSPanel(mQSPanel);
mHeader = qsContainer.getHeader();//quick_status_bar_expanded_header.xml
initSignalCluster(mHeader);
mHeader.setActivityStarter(PhoneStatusBar.this);
}
});
}
}
SystemUIFactory.java
public QSTileHost createQSTileHost(Context context, PhoneStatusBar statusBar,
BluetoothController bluetooth, LocationController location,
RotationLockController rotation, NetworkController network,
ZenModeController zen, HotspotController hotspot,
CastController cast, FlashlightController flashlight,
UserSwitcherController userSwitcher, UserInfoController userInfo,
KeyguardMonitor keyguard, SecurityController security,
BatteryController battery, StatusBarIconController iconController,
NextAlarmController nextAlarmController,
HotKnotController hotKnotController, RingController Ring,NfcController nfc)
{
return new QSTileHost(context, statusBar, bluetooth, location, rotation, network, zen,hotspot, cast, flashlight, userSwitcher, userInfo, keyguard, security, battery,iconController, nextAlarmController, hotKnotController, Ring,nfc);
}
QSTileHost.java:
public QSTileHost(Context context, PhoneStatusBar statusBar,
BluetoothController bluetooth, LocationController location,
RotationLockController rotation, NetworkController network,
ZenModeController zen, HotspotController hotspot,
CastController cast, FlashlightController flashlight,
UserSwitcherController userSwitcher, UserInfoController userInfo,
KeyguardMonitor keyguard, SecurityController security,
BatteryController battery, StatusBarIconController iconController,
NextAlarmController nextAlarmController,
HotKnotController hotknot, RingController Ring, NfcController nfc) {
mContext = context;
…......
//TILES_SETTING = "sysui_qs_tiles";
TunerService.get(mContext).addTunable(this, TILES_SETTING);
…......
}
TunerService.java:
........
public interface Tunable {
void onTuningChanged(String key, String newValue);
}
//QSTileHost implements QSTile.Host, Tunable
public void addTunable(Tunable tunable, String... keys) {//keys = sysui_qs_tiles
for (String key : keys) {
addTunable(tunable, key);
}
}
private void addTunable(Tunable tunable, String key) {//key = sysui_qs_tiles
…........
String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
Log.d("ylxing", "addTunable_value:"+ ((value == null)? "null":value));
tunable.onTuningChanged(key, value);//key = sysui_qs_tiles value == null
}
QSTileHost.java:
@Override
public void onTuningChanged(String key, String newValue) {//key = sysui_qs_tiles
if (!TILES_SETTING.equals(key)) {
return;
}
final List tileSpecs = loadTileSpecs(mContext, newValue);
.......
if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser)
return;
.......
final LinkedHashMap> newTiles = new LinkedHashMap<>();
for (String tileSpec : tileSpecs) {
.......
QSTile> tile = mTiles.get(tileSpec);
if (tile != null
&& (!(tile instanceof CustomTile) || ((CustomTile) tile)
.getUser() == currentUser)) {
tile.removeCallbacks();
newTiles.put(tileSpec, tile);
} else {
try {
tile = createTile(tileSpec);//QSTitle
if (tile != null && tile.isAvailable()) {
tile.setTileSpec(tileSpec);
newTiles.put(tileSpec, tile);
}
} catch (Throwable t) {
Log.w(TAG, "Error creating tile for spec: " + tileSpec, t);
}
}
}
mCurrentUser = currentUser;
mTileSpecs.clear();
mTileSpecs.addAll(tileSpecs); //默认快捷键"名称"容器
mTiles.clear();
mTiles.putAll(newTiles);//默认快捷键"实体键"容器
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onTilesChanged();
}
}
protected List loadTileSpecs(Context context, String tileList) {
if (tileList == null) {
tileList = context.getResources().getString(
R.string.quick_settings_tiles);// default
Log.d(TAG, "Loaded tile specs from config: " + tileList);
} else {
Log.d(TAG, "Loaded tile specs from setting: " + tileList);
}
final ArrayList tiles = new ArrayList();
boolean addedDefault = false;
for (String tile : tileList.split(",")) {
tile = tile.trim();
if (tile.isEmpty())
continue;
if (tile.equals("default")) {
if (!addedDefault) {
String defaultTiles = loadDefaultTiles(context);
tiles.addAll(Arrays.asList(defaultTiles.split(",")));
addedDefault = true;
}
} else {
tiles.add(tile);
}
}
return tiles;
}
/**
* 默认显示Titles
*/
private String loadDefaultTiles(Context context) {
final Resources res = context.getResources();
boolean enableNFC = res.getBoolean(R.bool.feature_systemui_nfc_support);
boolean enableAlexa = res
.getBoolean(com.android.internal.R.bool.def_tctfw_alexa_enable);
boolean enableBatter = res
.getBoolean(com.android.internal.R.bool.feature_tctfw_batterysaver_force_enable);
boolean enable2017Music = res
.getBoolean(com.android.internal.R.bool.feature_control_2017music_support);
String defaultTiles =
"wifi,bt,cell," +
"ring,airplane,rotation,"
"location,flashlight,hotspot," +
"night,cast"+ (enableNFC ? ",nfc" : ",") +
",inversion"+ (enableAlexa ? ",alexa" : ",") + ",TctRotation,audioEffect"
+ (enableBatter ? ",battery" : "");
return defaultTiles;
}
public QSTile> createTile(String tileSpec) {
IQuickSettingsPlugin quickSettingsPlugin = PluginManager
.getQuickSettingsPlugin(mContext);
boolean nfcQSPanel = mContext.getResources().getBoolean(
R.bool.feature_systemui_nfc_support);
if (tileSpec.equals("wifi"))
return new WifiTile(this);
else if (tileSpec.equals("bt"))
return new BluetoothTile(this);
else if (tileSpec.equals("cell"))
return new CellularTile(this);
else if (tileSpec.equals("dnd"))
return new DndTile(this);
else if (tileSpec.equals("inversion"))
return new ColorInversionTile(this);
else if (tileSpec.equals("airplane"))
return new AirplaneModeTile(this);
else if (tileSpec.equals("work"))
return new WorkModeTile(this);// 不显示
else if (tileSpec.equals("rotation"))
return new RotationLockTile(this);
else if (tileSpec.equals("flashlight"))
return new FlashlightTile(this);
else if (tileSpec.equals("location"))
return new LocationTile(this);
else if (tileSpec.equals("cast"))
return new CastTile(this);
else if (tileSpec.equals("hotspot"))
return new HotspotTile(this);
else if (tileSpec.equals("user"))
return new UserTile(this);// 不显示
else if (tileSpec.equals("nfc") && nfcQSPanel)
return new NfcTile(this);
else if (tileSpec.equals("battery"))
return new BatteryTile(this);
else if (tileSpec.equals("saver"))
return new DataSaverTile(this);
else if (tileSpec.equals("ring"))
return new RingTile(this);
else if (tileSpec.equals("screenshot"))
return new ScreenShotTile(this);
else if (tileSpec.equals("audioEffect"))
return new AudioEffectTile(this);
else if (tileSpec.equals("alexa")
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.def_tctfw_alexa_enable))
return new AlexaTile(this);
else if (tileSpec.equals("TctRotation"))
return new TctRotationTile(this);
else if (tileSpec.equals(NightModeTile.NIGHT_MODE_SPEC))
return new NightModeTile(this);
else if (tileSpec.equals("hotknot") && SIMHelper.isMtkHotKnotSupport())
return new HotKnotTile(this);
else if (tileSpec.equals("dataconnection")
&& !SIMHelper.isWifiOnlyDevice())
return new MobileDataTile(this);
else if (tileSpec.equals("simdataconnection")
&& !SIMHelper.isWifiOnlyDevice()
&& quickSettingsPlugin
.customizeAddQSTile(new SimDataConnectionTile(this)) != null) {
return (SimDataConnectionTile) quickSettingsPlugin
.customizeAddQSTile(new SimDataConnectionTile(this));
} else if (tileSpec.equals("dulsimsettings")
&& !SIMHelper.isWifiOnlyDevice()
&& quickSettingsPlugin
.customizeAddQSTile(new DualSimSettingsTile(this)) != null) {
return (DualSimSettingsTile) quickSettingsPlugin
.customizeAddQSTile(new DualSimSettingsTile(this));
} else if (tileSpec.equals("apnsettings")
&& !SIMHelper.isWifiOnlyDevice()
&& quickSettingsPlugin.customizeAddQSTile(new ApnSettingsTile(
this)) != null) {
return (ApnSettingsTile) quickSettingsPlugin
.customizeAddQSTile(new ApnSettingsTile(this));
} else if (quickSettingsPlugin.doOperatorSupportTile(tileSpec)) {
// WifiCalling
return (QSTile>) quickSettingsPlugin.createTile(this, tileSpec);
}
else if (tileSpec.startsWith(IntentTile.PREFIX))
return IntentTile.create(this, tileSpec);
else if (tileSpec.startsWith(CustomTile.PREFIX))
return CustomTile.create(this, tileSpec);
else if (mQuickSettingsPlugin.doOperatorSupportTile(tileSpec)) {
return (QSTile>) mQuickSettingsPlugin.createTile(this, tileSpec);
}
else {
Log.w(TAG, "Bad tile spec: " + tileSpec);
return null;
}
}
QSPanel.java
@Override
public void onTilesChanged() {
setTiles(mHost.getTiles());
}
public void setTiles(Collection> tiles) {
setTiles(tiles, false);
}
/**
* collapsedView = false 展开显示全部快捷键
* collapsedView = true 收起 显示5个快捷键
*/
public void setTiles(Collection> tiles, boolean collapsedView) {
for (TileRecord record : mRecords) {
mTileLayout.removeTile(record);
record.tile.removeCallback(record.callback);
}
mRecords.clear();
for (QSTile> tile : tiles) {
addTile(tile, collapsedView);
}
}
protected void addTile(final QSTile> tile, boolean collapsedView) {
final TileRecord r = new TileRecord();
tile.setQSpanel(this);
r.tile = tile;
r.tileView = createTileView(tile, collapsedView);//创建快捷键图标view
….......
r.tile.addCallback(callback);
r.callback = callback;
//每个title添加点击事件
final View.OnClickListener click = new View.OnClickListener() {
@Override
public void onClick(View v) {
onTileClick(r.tile);
}
};
//每个title添加长按事件
final View.OnLongClickListener longClick = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
r.tile.longClick();
return true;
}
};
//为每个快捷键添加点击+长按
r.tileView.init(click, longClick);
r.tile.refreshState();
//将创建的快捷键实例添加到容器mRecords
mRecords.add(r);
//将刚创建的快捷键添加到可滑动页面板区,即可显示在下拉通知栏中
if (mTileLayout != null) {
mTileLayout.addTile(r);
}
}