Android 5.1 SystemUi 之 StatusBar的简单分析

 

这篇博客真的写的很好!看完之后 帮助很大,因此我转载过来 希望更多人能看得到。


SystemServer.Java 启动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);
}

SystemUIService.java
    
    
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded();
}

SystemUIApplication.java
mServices[i].start() 启动了各种Service,但是它们并不是真正的Service ,继承了SystemUI.java这个抽象类,复写了start()方法
    
    
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
};
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]);
//调用所有的service的start方法
mServices[i].start();
 
//手机启动完成后,完成的事
if (mBootCompleted) {
mServices[i].onBootCompleted();
}
}
mServicesStarted = true;
}

因为我现在要分析status bar , 所以关注SystemBar.java 的start() 方法
    
    
@Override
public void start() {
if (DEBUG) Log.d(TAG, "start");
//ServiceMonitor是个监听器,这里就是监听这个BAR_SERVICE_COMPONENT是否改变
mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
//这里看到注释,如果Service不存在 ,就调用onNoService->createStatusBarFromConfig();
mServiceMonitor.start(); // will call onNoService if no remote service is found
}

ServiceMonitor.java
    
    
public ServiceMonitor(String ownerTag, boolean debug,
Context context, String settingKey, Callbacks callbacks) {
mTag = ownerTag + ".ServiceMonitor";
mDebug = debug;
mContext = context;
mSettingKey = settingKey;
mCallbacks = callbacks;
}
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);
}
这个类就是来监听这个 Settings . Secure . BAR_SERVICE_COMPONENT 的改变,并看情况如何启动Service。再看mHandler的处理

    
    
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() {
//获取Service的ComponentName
mServiceName = getComponentNameFromSetting();
if (mDebug) Log.d(mTag, "startService mServiceName=" + mServiceName);
if (mServiceName == null) {
mBound = false;
//如果没有Service,就回调,从之前的看,就是start PhoneStatusBar
mCallbacks.onNoService();
} else {
//喜闻乐见的bindService,说破天就是在启动PhoneStatusBar
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);
}
这里就是通过  getComponentNameFromSetting() 获取sevice的Component name,如果不存在就回调onNoservice方法,这个跟前面的注释实际就产生对应

SystemBar.java实现了这个回调接口,可以查到R.string.config_statusBarComponent的值 ,就是PhoneStatusBar
   
   
@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");
//<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>
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());
}

说破天,最终就是为了PhoneStatusBar.java的start() 方法

PhoneStatusBar.java
   
   
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);
 
/// M: [SystemUI] Support Smartbook Feature. @{
if (SIMHelper.isMtkSmartBookSupport()) {
/// M: [ALPS01097705] Query the plug-in state as soon as possible.
mIsDisplayDevice = SIMHelper.isSmartBookPluggedIn(mContext);
Log.v(TAG, "start, mIsDisplayDevice=" + mIsDisplayDevice);
}
/// @}
     
 
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
//添加Navigation Bar
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
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();
putComponent(DozeHost.class, mDozeServiceHost);
putComponent(PhoneStatusBar.class, this);
 
setControllerUsers();
 
notifyUserAboutHiddenNotifications();
 
mScreenPinningRequest = new ScreenPinningRequest(mContext);
}
现在要看的是StatusBar, 所以看super.start(),也就是 BaseStatusBar.java 的start()

BaseStatusBar.java
   
   
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);
 
mSettingsObserver.onChange(false); // set up
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);
//加载statusbarservice
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
//
mRecents = getComponent(RecentsComponent.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.
}
//就是为了调用这里,加载status bar
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);
 
// 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(BANNER_ACTION_CANCEL);
filter.addAction(BANNER_ACTION_SETUP);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, filter);
 
updateCurrentProfilesCache();
}
这里搞了一大堆,其实是就为了createAndAddWindows();  createAndAddWindows 在PhoneStatusBar中实现
    
    
@Override
public void createAndAddWindows() {
addStatusBarWindow();
}
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowManager = new StatusBarWindowManager(mContext);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
    
    
    
protected PhoneStatusBarView makeStatusBarView() {
final Context context = mContext;
 
Xlog.d(TAG, "makeStatusBarView : Start");
Resources res = context.getResources();
 
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
 
mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
 
/// M: Support "Change font size of phone".
Configuration config = res.getConfiguration();
 
/// M: [SystemUI] Support Smartbook Feature. @{
Log.v(TAG, "makeStatusBarView dump config information start ");
Log.v(TAG, " widthPixels = " + mDisplayMetrics.widthPixels);
Log.v(TAG, " heightPixels = " + mDisplayMetrics.heightPixels);
Log.v(TAG, " orientation = " + config.orientation);
Log.v(TAG, " config = " + config.toString());
Log.v(TAG, "makeStatusBarView dump config information end ");
/// @}
 
Xlog.d(TAG, "makeStatusBarView : inflate super_status_bar +");
//加载布局了
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
Xlog.d(TAG, "makeStatusBarView : inflate super_status_bar -");
//这个mStatusBarWindow就是status bar视图的根布局 ,监听事件,下拉
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);
}});
 
//status bar开始加载
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() && !SystemProperties.getBoolean("ro.config.low_ram", true)) {
mStatusBarWindow.setBackground(null);
mNotificationPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
R.color.notification_panel_solid_background)));
}
if (ENABLE_HEADS_UP) {
mHeadsUpNotificationView =
(HeadsUpNotificationView) View.inflate(context, R.layout.heads_up, null);
mHeadsUpNotificationView.setVisibility(View.GONE);
mHeadsUpNotificationView.setBar(this);
}
if (MULTIUSER_DEBUG) {
mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
R.id.header_debug_info);
mNotificationPanelDebugText.setVisibility(View.VISIBLE);
}
 
updateShowSearchHoldoff();
 
try {
boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
if (showNav) {
/// M: add for multi window @{
int layoutId = R.layout.navigation_bar;
if(RecentsActivity.FLOAT_WINDOW_SUPPORT){
layoutId = R.layout.navigation_bar_float_window;
}
mNavigationBarView =
(NavigationBarView) View.inflate(context, /*R.layout.navigation_bar*/layoutId, null);
/// @}
 
mNavigationBarView.setDisabledFlags(mDisabled);
mNavigationBarView.setBar(this);
mNavigationBarView.setOnVerticalChangedListener(
new NavigationBarView.OnVerticalChangedListener() {
@Override
public void onVerticalChanged(boolean isVertical) {
if (mSearchPanelView != null) {
mSearchPanelView.setHorizontal(isVertical);
}
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
}
 
// figure out which pixel-format to use for the status bar.
mPixelFormat = PixelFormat.OPAQUE;
//整个系统图标的根布局
mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
//整个系统图标的第二人父布局
mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons);
//状态图标 ,蓝牙,耳机
mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
//通知一块的图标 ,如运行时候出现的qq音乐
mNotificationIconArea = mStatusBarView.findViewById(R.id.notification_icon_area_inner);
mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
//整个status bar的根布局
mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
/*add calling code here */
/*calling the plugin for plmn display for orange*/
/// M: calling the plugin for plmn display for orange
Xlog.d(TAG, "over the call to plugin factory");
mPlmnDisplay = PluginFactory.getStatusBarPlmnPlugin(mContext).getPlmnTextView(mContext);
if (mPlmnDisplay != null) {
mPlmnDisplay.setVisibility(View.VISIBLE);
String str = (String) mPlmnDisplay.getText();
if (str == null)
Xlog.d(TAG, "No text in framework");
Xlog.d(TAG, "text of TextView = " + str);
mStatusBarContents.addView(mPlmnDisplay, 0);
mNotificationIcons.setCarrierText(mPlmnDisplay);
}
//下拉通知栏
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setPhoneStatusBar(this);
 
mKeyguardIconOverflowContainer =
(NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
mKeyguardIconOverflowContainer.setOnActivatedListener(this);
mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
mStackScroller.addView(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) {
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);
mScrimController = new ScrimController(scrimBehind, scrimInFront, mScrimSrcModeEnabled);
mScrimController.setBackDropView(mBackdrop);
mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context);
 
mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
mHeader.setActivityStarter(this);
//下面一系列的加载锁屏的status bar icon
mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
mStatusIconsKeyguard = (LinearLayout) mKeyguardStatusBar.findViewById(R.id.statusIcons);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
(KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text));
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
 
mTickerEnabled = res.getBoolean(R.bool.enable_ticker);
if (mTickerEnabled) {
final ViewStub tickerStub = (ViewStub) mStatusBarView.findViewById(R.id.ticker_stub);
if (tickerStub != null) {
mTickerView = tickerStub.inflate();
mTicker = new MyTicker(context, mStatusBarView);
 
TickerView tickerView = (TickerView) mStatusBarView.findViewById(R.id.tickerText);
tickerView.mTicker = mTicker;
}
}
 
mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
 
// set the inital view visibility
setAreThereNotifications();
 
// Background thread for any controllers that need it.
mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
 
// Other icons
Xlog.d(TAG, "makeStatusBarView : LocationControllerImpl");
mLocationController = new LocationControllerImpl(mContext); // will post a notification
Xlog.d(TAG, "makeStatusBarView : BatteryController");
mBatteryController = new BatteryController(mContext);
mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
@Override
public void onPowerSaveChanged() {
mHandler.post(mCheckBarModes);
if (mDozeServiceHost != null) {
mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
}
}
});
Xlog.d(TAG, "makeStatusBarView : NetworkControllerImpl");
mNetworkController = new NetworkControllerImpl(mContext);
Xlog.d(TAG, "makeStatusBarView : HotspotControllerImpl");
mHotspotController = new HotspotControllerImpl(mContext);
Xlog.d(TAG, "makeStatusBarView : BluetoothControllerImpl");
mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());
Xlog.d(TAG, "makeStatusBarView : SecurityControllerImpl");
mSecurityController = new SecurityControllerImpl(mContext);
 
/// M: add HotKnot in quicksetting @{
if (SIMHelper.isMtkHotKnotSupport()) {
Xlog.d(TAG, "makeStatusBarView : HotKnotControllerImpl");
mHotKnotController = new HotKnotControllerImpl(mContext);
} else {
mHotKnotController = null;
}
/// add HotKnot in quicksetting @}
 
/// M: add AudioProfile in quicksetting @{
if (SIMHelper.isMtkAudioProfilesSupport()) {
Xlog.d(TAG, "makeStatusBarView : AudioProfileControllerImpl");
mAudioProfileController = new AudioProfileControllerImpl(mContext);
} else {
mAudioProfileController = null;
}
/// M: add AudioProfile in quicksetting @}
 
/// M: add DataConnection in quicksetting @{
SIMHelper.setContext(mContext);
 
if(!SIMHelper.isWifiOnlyDevice()) {
Xlog.d(TAG, "makeStatusBarView : DataConnectionControllerImpl");
mDataConnectionController = new DataConnectionControllerImpl(mContext);
} else {
mDataConnectionController = null;
}
/// M: add DataConnection in quicksetting @}
 
if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
Xlog.d(TAG, "makeStatusBarView : RotationLockControllerImpl");
mRotationLockController = new RotationLockControllerImpl(mContext);
}
Xlog.d(TAG, "makeStatusBarView : UserInfoController +");
mUserInfoController = new UserInfoController(mContext);
Xlog.d(TAG, "makeStatusBarView : UserInfoController -");
mVolumeComponent = getComponent(VolumeComponent.class);
if (mVolumeComponent != null) {
mZenModeController = mVolumeComponent.getZenController();
}
// M: Remove CastTile when WFD is not support in quicksetting
if (SIMHelper.isWifiDisplaySupport()) {
Xlog.d(TAG, "makeStatusBarView : CastControllerImpl +");
mCastController = new CastControllerImpl(mContext);
Xlog.d(TAG, "makeStatusBarView : CastControllerImpl -");
}
//信号图标:vpn wifi sim
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.addSignalCluster(signalCluster);
mNetworkController.addSignalCluster(signalClusterKeyguard);
mNetworkController.addSignalCluster(signalClusterQs);
signalCluster.setSecurityController(mSecurityController);
signalCluster.setNetworkController(mNetworkController);
signalClusterKeyguard.setSecurityController(mSecurityController);
signalClusterKeyguard.setNetworkController(mNetworkController);
signalClusterQs.setSecurityController(mSecurityController);
signalClusterQs.setNetworkController(mNetworkController);
/// M: [ALPS01967373] set EmergencyCallsOnly text @{
mNetworkController.addEmergencyListener(new NetworkControllerImpl.EmergencyListener() {
@Override
public void setEmergencyCallsOnly(boolean emergencyOnly) {
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
if (DEBUG) {
Xlog.d(TAG, "setEmergencyCallsOnly: " + emergencyOnly +
", voiceFeature: " + isAPhone);
}
if (isAPhone || emergencyOnly == false) {
mHeader.setShowEmergencyCallsOnly(emergencyOnly);
}
}
});
/// M: [ALPS01967373] set EmergencyCallsOnly text @}
//运营商图标
mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
mShowCarrierInPanel = (mCarrierLabel != null);
if (DEBUG) Log.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel);
/// M: Support "Operator plugin - Customize Carrier Label for PLMN" @{
mStatusBarPlmnPlugin = PluginFactory.getStatusBarPlmnPlugin(context);
/// M: Support "Operator plugin - Customize Carrier Label for PLMN" @}
if (mShowCarrierInPanel) {
mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);
 
mNetworkController.addCarrierLabel(new NetworkControllerImpl.CarrierLabelListener() {
@Override
public void setCarrierLabel(String label) {
mCarrierLabel.setText(label);
if (mNetworkController.hasMobileDataFeature()) {
if (TextUtils.isEmpty(label)) {
mCarrierLabel.setVisibility(View.GONE);
} else {
/// M: Support "Operator plugin - Customize Carrier Label for PLMN" @{
if (!(mStatusBarPlmnPlugin != null
&& mStatusBarPlmnPlugin.supportCustomizeCarrierLabel())) {
mCarrierLabel.setVisibility(View.VISIBLE);
}
/// M: Support "Operator plugin - Customize Carrier Label for PLMN" @}
}
}
}
});
}
 
/// M: Support "Operator plugin - Customize Carrier Label for PLMN". @{
if (supportCustomizeCarrierLabel()) {
mCustomizeCarrierLabel = mStatusBarPlmnPlugin.customizeCarrierLabel(
mNotificationPanel, mCarrierLabel);
}
/// M: Support "Operator plugin - Customize Carrier Label for PLMN". @}
 
Xlog.d(TAG, "makeStatusBarView : FlashlightController +");
mFlashlightController = new FlashlightController(mContext);
Xlog.d(TAG, "makeStatusBarView : FlashlightController -");
mKeyguardBottomArea.setFlashlightController(mFlashlightController);
mKeyguardBottomArea.setPhoneStatusBar(this);
Xlog.d(TAG, "makeStatusBarView : AccessibilityController");
mAccessibilityController = new AccessibilityController(mContext);
mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
Xlog.d(TAG, "makeStatusBarView : NextAlarmController +");
mNextAlarmController = new NextAlarmController(mContext);
Xlog.d(TAG, "makeStatusBarView : NextAlarmController -");
mKeyguardMonitor = new KeyguardMonitor();
if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {
Xlog.d(TAG, "makeStatusBarView : UserSwitcherController +");
mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor);
Xlog.d(TAG, "makeStatusBarView : UserSwitcherController -");
}
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,
/// M: add HotKnot in quicksetting
mHotKnotController,
/// M: add AudioProfile in quicksetting
mAudioProfileController,
/// M: add DataConnection in quicksetting
mDataConnectionController
);
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);
mUserInfoController.reloadUserInfo();
 
mHeader.setBatteryController(mBatteryController);
((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
mBatteryController);
//锁屏界面的设置battery改变的监听器
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);
if (DEBUG_MEDIA_FAKE_ARTWORK) {
filter.addAction("fake_artwork");
}
filter.addAction(ACTION_DEMO);
context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
 
/// M: [SystemUI] Support Smartbook Feature. @{
if (SIMHelper.isMtkSmartBookSupport()) {
IntentFilter mFilter = new IntentFilter(Intent.ACTION_SMARTBOOK_PLUG);
context.registerReceiver(mDisplayDevicePluginReceiver, mFilter);
Log.v(TAG, "makeStatusBarView, isSmartBookPluggedIn="
+ SIMHelper.isSmartBookPluggedIn(context));
}
/// @}
 
// listen for USER_SETUP_COMPLETE setting (per-user)
resetUserSetupObserver();
 
startGlyphRasterizeHack();
Xlog.d(TAG, "makeStatusBarView : End");
return mStatusBarView;
}
mStatusBarWindow=(StatusBarWindowView)View.inflate(context,
R.layout.super_status_bar,null);
这个 super_status_bar.xml文件加载了
       
       
 
 
 
<com.android.systemui.statusbar.phone.StatusBarWindowView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
 
<com.android.systemui.statusbar.BackDropView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
>
<ImageView android:id="@+id/backdrop_back"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="match_parent" />
<ImageView android:id="@+id/backdrop_front"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:visibility="invisible" />
</com.android.systemui.statusbar.BackDropView>
 
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_behind"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:importantForAccessibility="no" />
 
<include layout="@layout/status_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_height" />
 
<FrameLayout android:id="@+id/brightness_mirror"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="wrap_content"
android:layout_gravity="@integer/notification_panel_layout_gravity"
android:paddingLeft="@dimen/notification_side_padding"
android:paddingRight="@dimen/notification_side_padding"
android:visibility="gone">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="2dp"
android:background="@drawable/brightness_mirror_background">
<include layout="@layout/quick_settings_brightness_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
</FrameLayout>
 
<!--加载锁屏界面的status bar-->
<com.android.systemui.statusbar.phone.PanelHolder
android:id="@+id/panel_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" >
<include layout="@layout/status_bar_expanded"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</com.android.systemui.statusbar.phone.PanelHolder>
 
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_in_front"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:importantForAccessibility="no" />
 
</com.android.systemui.statusbar.phone.StatusBarWindowView>

    <include layout="@layout/status_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/status_bar_height" />
这就是我们的status bar的图标了 
status_bar.xml

    
    
<com.android.systemui.statusbar.phone.PhoneStatusBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/status_bar"
android:background="@drawable/system_bar_background"
android:orientation="vertical"
android:focusable="true"
android:descendantFocusability="afterDescendants"
>
 
<ImageView
android:id="@+id/notification_lights_out"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
android:paddingStart="6dip"
android:paddingBottom="2dip"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:visibility="gone"
/>
 
<LinearLayout android:id="@+id/status_bar_contents"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="6dp"
android:paddingEnd="8dp"
android:orientation="horizontal"
>
 
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
>
<!-- The alpha of this area is both controlled from PhoneStatusBarTransitions and
PhoneStatusBar (DISABLE_NOTIFICATION_ICONS), so we need two views here. -->
<com.android.keyguard.AlphaOptimizedLinearLayout
android:id="@+id/notification_icon_area_inner"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
android:src="@drawable/stat_notify_more"
android:visibility="gone"
/>
<com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:gravity="center_vertical"
android:orientation="horizontal"/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
 
<com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
>
 
<include layout="@layout/system_icons" />
 
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:singleLine="true"
android:paddingStart="7dp"
android:gravity="center_vertical|start"
/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
</LinearLayout>
 
<ViewStub
android:id="@+id/ticker_stub"
android:inflatedId="@+id/ticker"
android:layout="@layout/status_bar_ticker"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
 
</com.android.systemui.statusbar.phone.PhoneStatusBarView>

notification_icon_area_inner是通知图标 ,例如听QQ音乐的时候 ,会在手机左边区域显示QQ音乐的图标
system_icon_area里面有个clock,当然就是最右边的时间了 
中间<include layout="@layout/system_icons" /> 就是系统的图标了


system_icon.xml

    
    
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/system_icons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical">
 
<com.android.keyguard.AlphaOptimizedLinearLayout
android:id="@+id/statusIcons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal"/>
 
<include layout="@layout/signal_cluster_view"
android:id="@+id/signal_cluster"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2.5dp"/>
 
<!-- battery must be padded below to match assets -->
<com.android.systemui.BatteryMeterView android:id="@+id/battery"
android:layout_height="14.5dp"
android:layout_width="9.5dp"
android:layout_marginBottom="@dimen/battery_margin_bottom"/>
</LinearLayout>
第一个,statusIcons,状态图标 , 就是蓝牙,耳机的图标 
第二个,signal_cluster_view,信号图标, 也就是 vpn wifi , SIM 
signal_cluster_view.xml
    
    
<com.android.systemui.statusbar.SignalClusterView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingEnd="@dimen/signal_cluster_battery_padding"
>
<ImageView
android:id="@+id/vpn"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingEnd="6dp"
android:src="@drawable/stat_sys_vpn_ic"
/>
<FrameLayout
android:id="@+id/wifi_combo"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
<ImageView
android:id="@+id/wifi_signal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
</FrameLayout>
<View
android:id="@+id/wifi_signal_spacer"
android:layout_width="4dp"
android:layout_height="4dp"
android:visibility="gone"
/>
<!-- M: Support "SystemUI - VoLTE icon". @{ -->
<ImageView
android:id="@+id/volte_icon"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="gone"
/>
<!-- M: Support "SystemUI - VoLTE icon". }@ -->
<!-- M: Support "Default SIM Indicator". @{ -->
<ImageView
android:id="@+id/sim_indicator_internet_or_alwaysask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginEnd="3dip"
/>
<!-- M: Support "Default SIM Indicator". }@ -->
<LinearLayout
android:id="@+id/mobile_signal_group"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
>
</LinearLayout>
<ImageView
android:id="@+id/no_sims"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/stat_sys_no_sims"
/>
<View
android:id="@+id/wifi_airplane_spacer"
android:layout_width="4dp"
android:layout_height="4dp"
android:visibility="gone"
/>
<ImageView
android:id="@+id/airplane"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
</com.android.systemui.statusbar.SignalClusterView>

最后一个 @+id/battery 当然就是电池了

但是,但是,我们看手机的时候,居然没有电量百分比显示出来 ,这让很多客户就有点恼火,后面再说

再看super_status_bar.xml最后一个布局
    
    
<!--加载锁屏界面的status bar-->
<com.android.systemui.statusbar.phone.PanelHolder
android:id="@+id/panel_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" >
<include layout="@layout/status_bar_expanded"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</com.android.systemui.statusbar.phone.PanelHolder>

status_bar_expanded.xml
    
    
<include
layout="@layout/keyguard_status_bar"
android:visibility="invisible" />

keyguard_status_bar.xml
    
    
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2014 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
 
<!-- Extends RelativeLayout -->
<com.android.systemui.statusbar.phone.KeyguardStatusBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/keyguard_header"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_header_height_keyguard"
android:baselineAligned="false"
>
 
<com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
android:layout_width="@dimen/multi_user_switch_width_keyguard"
android:layout_height="@dimen/status_bar_header_height_keyguard"
android:layout_alignParentEnd="true"
android:background="@drawable/ripple_drawable"
android:layout_marginEnd="@dimen/multi_user_switch_keyguard_margin">
<ImageView android:id="@+id/multi_user_avatar"
android:layout_width="@dimen/multi_user_avatar_keyguard_size"
android:layout_height="@dimen/multi_user_avatar_keyguard_size"
android:layout_gravity="center"
android:scaleType="centerInside"/>
</com.android.systemui.statusbar.phone.MultiUserSwitch>
 
<LinearLayout android:id="@+id/system_icons_super_container"
android:layout_width="wrap_content"
android:layout_height="@dimen/status_bar_header_height"
android:layout_toStartOf="@id/multi_user_switch"
android:layout_alignWithParentIfMissing="true"
android:layout_marginStart="16dp"
android:paddingEnd="@dimen/system_icons_keyguard_padding_end">
<FrameLayout android:id="@+id/system_icons_container"
android:layout_width="wrap_content"
android:layout_height="@dimen/status_bar_height"
android:layout_gravity="center_vertical"
>
<include layout="@layout/system_icons" />
</FrameLayout>
<TextView android:id="@+id/battery_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/header_battery_margin_keyguard"
android:paddingEnd="@dimen/battery_level_padding_end"
android:textColor="#ffffff"
android:visibility="gone"
android:textSize="@dimen/battery_level_text_size"
android:importantForAccessibility="noHideDescendants"/>
</LinearLayout>
 
<com.android.keyguard.CarrierText
android:id="@+id/keyguard_carrier_text"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_header_height_keyguard"
android:layout_marginStart="@dimen/keyguard_carrier_text_margin"
android:layout_toStartOf="@id/system_icons_super_container"
android:gravity="center_vertical"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#ffffff"
android:singleLine="true" />
</com.android.systemui.statusbar.phone.KeyguardStatusBarView>
看看手机,就知道这是什么图标了,但是但是,这里他妈的居然出现了 @+id/battery_level ,但是这个battery_level可不是你想显示就显示的,它要在充电状态下才显示电量到底有多少,fuck~, 真是他妈的看不懂这个设计,难道就是为了简化不必要的设计



猜你喜欢

转载自blog.csdn.net/gjy_it/article/details/73864594