This article is based on Android 10 source code analysis.
The StatusBar consists of three parts
- The leftmost section shows the operator, time, and notification ICONS
- The rightmost section shows the system icon, which consists of a status icon (such as wifi, BT) and a battery icon.
- There’s another area in the middle that I won’t talk about.
This article focuses on how status ICONS (e.g. Wifi, Bt) can be displayed under control.
Status bar icon controller
Status icon in the status bar control, will be done by an interface, this interface is StatusBarIconController, and its implementation class is StatusBarIconControllerImpl.
Let’s start with its annotations and inheritance structure
/** * Receives the callbacks from CommandQueue related to icons and tracks the state of * all the icons. Dispatches this state to any IconManagers that are currently * registered with it. */
@Singleton
public class StatusBarIconControllerImpl extends StatusBarIconList
implements Tunable.CommandQueue.Callbacks.StatusBarIconController {}
Copy the code
The comment says that it receives callbacks about ICONS from CommandQueue and distributes them to the registered IconManager. However, it does more than that. SystemUI can call it from anywhere to set ICONS for the status bar, because it also implements the StatusBarIconController interface, which is described below
public interface StatusBarIconController {
// Set the icon
public void setIcon(String slot, int resourceId, CharSequence contentDescription);
public void setIcon(String slot, StatusBarIcon icon);
// Set the wifi icon
public void setSignalIcon(String slot, WifiIconState state);
// Set the phone signal icon
public void setMobileIcons(String slot, List<MobileIconState> states);
// Set icon visibility
public void setIconVisibility(String slot, boolean b);
}
Copy the code
With that in mind, now look at what its constructor does
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
public StatusBarIconControllerImpl(Context context) {
mContext = context;
// Save the status bar icon name through the parent class
super(context.getResources().getStringArray(
com.android.internal.R.array.config_statusBarIcons));
// Register a callback to CommandQueue
SysUiServiceProvider.getComponent(context, CommandQueue.class)
.addCallback(this);
// Implement the blacklist function, the principle is to listen to the database blacklist value
Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
}
Copy the code
There are three main things going on here
- Save the name of the icon in the status bar.
- to
CommandQueue
Register a callback. - Listen to the database blacklist.
Blacklist function is very simple, is to monitor the database on the blacklist URI changes, and then update the blacklist list, and then set the icon when to query the blacklist, and then decide how to set.
CommandQueue is a Binder class registered with StatusBar#start() to receive messages from the server, which registers a callback on the server. And StatusBarIconControllerImpl CommandQueue to register the callback, it is to get information about icon, so that it can be correctly set icon in the status bar.
Now look at the config_statusBarIcons array that saves the ICONS ‘names
// frameworks/base/core/res/res/values/config.xml
<string-array name="config_statusBarIcons">
<item><xliff:g id="id">@string/status_bar_alarm_clock</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_rotate</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_headset</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_data_saver</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_ime</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sync_failing</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sync_active</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_nfc</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_tty</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_speakerphone</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_cdma_eri</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_data_connection</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_phone_evdo_signal</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_phone_signal</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_secure</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_managed_profile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_cast</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_vpn</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_bluetooth</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_camera</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_microphone</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_location</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mute</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_volume</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_zen</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_ethernet</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_wifi</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
</string-array>
Copy the code
This array defines not only the name of the icon, but also the order in which the icon is displayed, for example, wifi must come before the battery icon.
Register icon Manager
This article is to discuss the status icon control, according to the above said, it must first registered an icon with the StatusBarIconControllerImpl manager, according to the above can be speculated that this is implemented in CollapsedStatusBarFragment
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
// ...
// r.id.satusicons represent status icon areas, such as BT, wifi
// Create an icon manager in the status icon area
mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
/ / to StatusBarIconControllerImpl registration manager icon
Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
// ...
}
Copy the code
Set status icon
With everything in place, how does the status icon set work? In StatusBar#start(), it is set by some policy
// frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public void start(a) {
// ...
// Call the icon policy to install/update all ICONS
mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);
// ...
}
Copy the code
All status ICONS are set in these two policy classes. How is the cell phone signal icon set? It’s in StatusBarSignalPolicy. Okay
public StatusBarSignalPolicy(Context context, StatusBarIconController iconController) {
mContext = context;
// Get the signal icon name
mSlotMobile = mContext.getString(com.android.internal.R.string.status_bar_mobile);
/ / this is StatusBarIconContrllerImpl object
mIconController = iconController;
// Register the network listener
mNetworkController = Dependency.get(NetworkController.class);
mNetworkController.addCallback(this);
}
Copy the code
To set an icon, first get the name of the icon, which can be obtained from the array mentioned above.
It then registers a network listener to get events about the phone signal
@Override
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut, int volteIcon,
String typeContentDescription, String description, boolean isWide,
int subId, boolean roaming) {
// ...
// Set the signal icon. The first parameter indicates the icon name and the second parameter indicates the status
mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));
// ..
}
Copy the code
As you can see, this is implemented via StatusBarIconController#setMobileIcons(), but I won’t go into the details.
Setting ICONS through the StatusBarIconController interface is the same
- Get icon name
- Listen for an event
- through
StatusBarIconController
Corresponding method setting icon.
Set the icon without SIM card
Before, the company needed to set an icon without SIM. In fact, this interface has been provided by the system, which is in StatusBarSignalPolicy
public void setNoSims(boolean show, boolean simDetected) {
String mobileSlot = mContext.getString(com.android.internal.R.string.status_bar_mobile);
if(show && ! simDetected) { mIconController.setIcon(mobileSlot, R.drawable.ic_no_sim_black_24dp,"no_sim");
mIconController.setIconVisibility(mobileSlot, true);
} else {
mIconController.setIconVisibility(mobileSlot, false); }}Copy the code
Follow the formula, so easy!