9.0 SystemUI 状态栏 系统状态图标初始化流程

 

 

 

 

statusIcons 代表系统状态图标  例如耳机、蓝牙、位置信息、网络等等,具体定义在config_statusBarIcons中。

在StatusBarIconControllerImpl.java的构造函数中被用来初始化StatusBarIconList.java中的

private ArrayList<Slot> mSlots = new ArrayList<>();

 

以后添加跟更新图标说所的slot跟index就是根据这个顺序来对应排序的

比如slot =headset   index =3;

 

一:其布局文件

system_icons.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/system_icons"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical">
 
    <com.android.systemui.statusbar.phone.StatusIconContainer android:id="@+id/statusIcons"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:paddingEnd="@dimen/signal_cluster_battery_padding"
        android:gravity="center_vertical"
        android:orientation="horizontal"/>
 
    <com.android.systemui.BatteryMeterView android:id="@+id/battery"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:clipToPadding="false"
        android:clipChildren="false" />
</LinearLayout>

我们的system_icons.xml被include在status_bar.xml中,在CollapsedStatusBarFragment.java中被一同初始化。
 

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.status_bar, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
        android.util.Log.d("lgy_debug_systemui","CollapsedStatusBarFragment.java addIconGroup");	
        Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);

    }

初始化状态图标:

以我自己添加的Log作为主线思路。

statusBar.java start()..PhoneStatusBarPolicy .//在statusBar.java的start方法中初始化PhoneStatusBarPolicy 
PhoneStatusBarPolicy.java--->PhoneStatusBarPolicy() .//PhoneStatusBarPolicy的构造方法
StatusBarIconControllerImpl.java setIconVisibility slot =tty// updateTTY();
StatusBarIconControllerImpl.java setIconVisibility visibility =false// updateTTY();
PhoneStatusBarPolicy.java--->updateBluetooth() .//
StatusBarIconControllerImpl.java setIcon  slot = bluetooth
StatusBarIconControllerImpl.java setIcon  resourceId = 2131231688
StatusBarIconControllerImpl.java setIcon  holder = null
StatusBarIconControllerImpl.java 5555 setIcon index =15
StatusBarIconControllerImpl.java 5555 setIcon isNew =true
StatusBarIconControllerImpl.java addSystemIcon 
StatusBarIconControllerImpl.java addSystemIcon  mIconGroups.size =0//mIconGroups size为0,不会跑onIconAdded
StatusBarIconControllerImpl.java setIconVisibility slot =bluetooth
StatusBarIconControllerImpl.java setIconVisibility visibility =false

KeyguardstatusBarView.java--->onAttachedToWindow begin addIconGroup//在KeyguardstatusBarView
StatusBarIconControllerImpl.java addIconGroup  mIconGroups.size() =1
StatusBarIconControllerImpl.java addIconGroup  allSlots.size() =30
StatusBarIconControllerImpl.java addIconGroup  begion IconAdded 
StatusBarIconController.java--->onIconAdded 222
StatusBarIconController.java--->addHolder addHolder.getType =   0
StatusBarIconController.java--->addHolder slot =   bluetooth
tatusBarIconController.java--->addIcon  2222 //TintedIconManager.onIconAdded()

CollapsedStatusBarFragment.java addIconGroup
StatusBarIconControllerImpl.java addIconGroup  mIconGroups.size() =2
StatusBarIconControllerImpl.java addIconGroup  allSlots.size() =30
StatusBarIconControllerImpl.java addIconGroup  begion IconAdded 
StatusBarIconController.java--->onIconAdded 3333 //DarkIconManager.onIconAdded()
StatusBarIconController.java--->addHolder addHolder.getType =   0
StatusBarIconController.java--->addHolder slot =   bluetooth
StatusBarIconController.java--->addIcon  2222
DarkIconDispatherImpl.java addDarkReceiver

QuickStatusBarHeader.java--->onAttachedToWindow begin addIconGroup
StatusBarIconControllerImpl.java addIconGroup  mIconGroups.size() =3
StatusBarIconControllerImpl.java addIconGroup  allSlots.size() =30
StatusBarIconControllerImpl.java addIconGroup  begion IconAdded 
StatusBarIconController.java--->onIconAdded 222 //TintedIconManager.onIconAdded()
StatusBarIconController.java--->addHolder addHolder.getType =   0
StatusBarIconController.java--->addHolder slot =   bluetooth
StatusBarIconController.java--->addIcon  2222

 

 1 StatusBar.java 初始化PhoneStatusBarPolicy



@Override
public void start() {

        mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
}

protected void makeStatusBarView() {

        mIconController = Dependency.get(StatusBarIconController.class);

}

 

那么来看下PhoneStatusBarPolicy的构造函数

    public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) {
        mContext = context;
        mIconController = iconController;
        mCast = Dependency.get(CastController.class);
        mHotspot = Dependency.get(HotspotController.class);
        mBluetooth = Dependency.get(BluetoothController.class);
        mNextAlarmController = Dependency.get(NextAlarmController.class);
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        mUserInfoController = Dependency.get(UserInfoController.class);
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mRotationLockController = Dependency.get(RotationLockController.class);
        mDataSaver = Dependency.get(DataSaverController.class);
        mZenController = Dependency.get(ZenModeController.class);
        mProvisionedController = Dependency.get(DeviceProvisionedController.class);
        mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
        mLocationController = Dependency.get(LocationController.class);

        mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
        mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
        mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth);
        mSlotTty = context.getString(com.android.internal.R.string.status_bar_tty);
        mSlotZen = context.getString(com.android.internal.R.string.status_bar_zen);
        mSlotVolume = context.getString(com.android.internal.R.string.status_bar_volume);
        mSlotAlarmClock = context.getString(com.android.internal.R.string.status_bar_alarm_clock);
        mSlotManagedProfile = context.getString(
                com.android.internal.R.string.status_bar_managed_profile);
        mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
        mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
        mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
        mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
        // M: ignor for BSP+
        // mSlotEmbms = context.getString(com.android.internal.R.string.status_bar_embms);
        mSlotEmbms = "embms";

        // listen for broadcasts
        IntentFilter filter = new IntentFilter();
        /// M: [Multi-User] Will register this action using special receiver.
        //filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
        filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
        filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
        filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
        /// M: [Multi-User] Add user switched action for updating possible alarm icon.
        filter.addAction(Intent.ACTION_USER_SWITCHED);
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);

        /// M: Add icon for embms session.
        filter.addAction(TelephonyIntents.ACTION_EMBMS_SESSION_STATUS_CHANGED);
        mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
        /// M: [Multi-User] Register Alarm intent by user
        registerAlarmClockChanged(UserHandle.USER_OWNER, false);

        // listen for user / profile change.
        try {
            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
        } catch (RemoteException e) {
            // Ignore
        }
				android.util.Log.d("lgy_debug_systemui","PhoneStatusBarPolicy.java--->PhoneStatusBarPolicy() ."); 
        // TTY status
        updateTTY();

        // bluetooth status
        updateBluetooth();

        //eMBMS status
        mIconController.setIcon(mSlotEmbms, R.drawable.stat_sys_embms, null);
        mIconController.setIconVisibility(mSlotEmbms, false);


        // Alarm clock
        mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
        mIconController.setIconVisibility(mSlotAlarmClock, false);

        // zen
        mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
        mIconController.setIconVisibility(mSlotZen, false);

        // volume
        mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);
        mIconController.setIconVisibility(mSlotVolume, false);
        updateVolumeZen();

        // cast
        mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
        mIconController.setIconVisibility(mSlotCast, false);

        // hotspot
        mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
                mContext.getString(R.string.accessibility_status_bar_hotspot));
        mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());

        // managed profile
        mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
                mContext.getString(R.string.accessibility_managed_profile));
        mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);

        // data saver
        mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
                context.getString(R.string.accessibility_data_saver_on));
        mIconController.setIconVisibility(mSlotDataSaver, false);

        mRotationLockController.addCallback(this);
        mBluetooth.addCallback(this);
        mProvisionedController.addCallback(this);
        mZenController.addCallback(this);
        mCast.addCallback(mCastCallback);
        mHotspot.addCallback(mHotspotCallback);
        mNextAlarmController.addCallback(mNextAlarmCallback);
        mDataSaver.addCallback(this);
        mKeyguardMonitor.addCallback(this);
        mLocationController.addCallback(this);

        SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);

        // Clear out all old notifications on startup (only present in the case where sysui dies)
        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
        for (StatusBarNotification notification : noMan.getActiveNotifications()) {
            if (notification.getId() == SystemMessage.NOTE_INSTANT_APPS) {
                noMan.cancel(notification.getTag(), notification.getId());
            }
        }
        DockedStackExistsListener.register(exists -> {
            mDockedStackExists = exists;
            updateForegroundInstantApps();
        });
    }

不难看出,在构造器里面主要干了以下几件事:

1,初始化各个Slot的名字以及其控制类接口.

   以Slot为bluetooth为例

      mBluetooth = Dependency.get(BluetoothController.class);

      mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth);
public interface BluetoothController extends CallbackController<Callback>, Dumpable {
    boolean isBluetoothSupported();
    boolean isBluetoothEnabled();

    int getBluetoothState();

    boolean isBluetoothConnected();
    boolean isBluetoothConnecting();
    String getConnectedDeviceName();
    void setBluetoothEnabled(boolean enabled);
    Collection<CachedBluetoothDevice> getDevices();
    void connect(CachedBluetoothDevice device);
    void disconnect(CachedBluetoothDevice device);
    boolean canConfigBluetooth();

    int getMaxConnectionState(CachedBluetoothDevice device);
    int getBondState(CachedBluetoothDevice device);
    List<CachedBluetoothDevice> getConnectedDevices();

    public interface Callback {
        void onBluetoothStateChange(boolean enabled);
        void onBluetoothDevicesChanged();
    }
}

BluetoothController 的最终实现者是BluetoothControllerImpl,聪明的小伙伴应该从接口名字就能看出来,这个类就是对我们蓝牙状态的管控类了。

2,注册想要监听的广播,如ACTION_HEADSET_PLUG、ACTION_SIM_STATE_CHANGED、ACTION_USER_SWITCHED

        filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);

  注册这些感兴趣的广播action,主要是通过其状态来更新其对应在对应状态栏上的显示状态。来看mIntentReceiver;  

    /*private*/ BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case AudioManager.RINGER_MODE_CHANGED_ACTION:
                case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
                    updateVolumeZen();
                    break;
                case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
                    // Avoid rebroadcast because SysUI is direct boot aware.
                    if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK,
                            false)) {
                        break;
                    }
                    updateSimState(intent);
                    break;
                case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED:
                    updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
                            TelecomManager.TTY_MODE_OFF));
                    break;
                case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
                case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
                case Intent.ACTION_MANAGED_PROFILE_REMOVED:
                    updateManagedProfile();
                    break;
                case AudioManager.ACTION_HEADSET_PLUG:
                    updateHeadsetPlug(intent);
                    break;
                /// M: [Multi-User] Register Alarm intent by user @{
                case Intent.ACTION_USER_SWITCHED:
                    updateAlarm();
                    int newUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                    registerAlarmClockChanged(newUserId, true);
                    break;
                /// M: @}
                /// M: embms session status intent @{
                case TelephonyIntents.ACTION_EMBMS_SESSION_STATUS_CHANGED:
                    updateEmbmsState(intent);
                    break;
                /// M: @}
            }
        }
    };

3,开始初始化各个Slot的图标以及显示状态

 updateTTY();
// bluetooth status
 updateBluetooth();

//eMBMS status
 mIconController.setIcon(mSlotEmbms, R.drawable.stat_sys_embms, null);
 mIconController.setIconVisibility(mSlotEmbms, false);
// hotspot
 mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
                mContext.getString(R.string.accessibility_status_bar_hotspot));
 mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());

来看bluetootch 是如何更新其状态图标的

    private final void updateBluetooth() {
    	  android.util.Log.d("lgy_debug_systemui","PhoneStatusBarPolicy.java--->updateBluetooth() ."); 
        int iconId = R.drawable.stat_sys_data_bluetooth;//显示蓝牙图标资源
        String contentDescription =
                mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
        boolean bluetoothVisible = false;
        if (mBluetooth != null) {
            if (mBluetooth.isBluetoothConnected()) {//蓝牙开关是否打开
                iconId = R.drawable.stat_sys_data_bluetooth_connected;
                contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
                bluetoothVisible = mBluetooth.isBluetoothEnabled();//
            }
        }

        mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);//设置蓝牙图标
        mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);//蓝牙图标与否显示在状态栏上否
    }

最后都是调用mIconController 来设置图标资源与控制是否在状态栏上显示的;

        mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);//设置蓝牙图标
        mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);//蓝牙图标与否显示在状态栏上

mIconController 是StatusBarIconController,它是一个interface,其实现者是StatusBarIconControllerImpl;

 StatusBarIconControllerImpl.java 

  @Override
    public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
        int index = getSlotIndex(slot);
        StatusBarIconHolder holder = getIcon(index, 0);
        android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java setIcon  slot = "+slot);
        android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java setIcon  resourceId = "+resourceId);
        android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java setIcon  holder = "+holder);	
        if (holder == null) {
            StatusBarIcon icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
                    Icon.createWithResource(
                            mContext, resourceId), 0, 0, contentDescription);
            holder = StatusBarIconHolder.fromIcon(icon);
            setIcon(index, holder);
        } else {
            holder.getIcon().icon = Icon.createWithResource(mContext, resourceId);
            holder.getIcon().contentDescription = contentDescription;
            handleSet(index, holder);
        }
    }

D lgy_debug_systemui: StatusBarIconControllerImpl.java setIcon  holder = null

首先获取holder,然后判断其是否为null,第一次开机holder 为null,所以都会走setIcon(index, holder);

    @Override
    public void setIcon(int index, @NonNull StatusBarIconHolder holder) {
        boolean isNew = getIcon(index, holder.getTag()) == null;
        android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java 5555 setIcon index ="+index);
        android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java 5555 setIcon isNew="+isNew);
        super.setIcon(index, holder);

        if (isNew) {
            addSystemIcon(index, holder);
        } else {
            handleSet(index, holder);
        }
    }

D lgy_debug_systemui: StatusBarIconControllerImpl.java 5555 setIcon isNew =true

判断是不是新要加的,isNew为true,走 addSystemIcon(index, holder);

    private void addSystemIcon(int index, StatusBarIconHolder holder) {
    	android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java addSystemIcon  ");
        String slot = getSlotName(index);
        int viewIndex = getViewIndex(index, holder.getTag());
        boolean blocked = mIconBlacklist.contains(slot);
        android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java addSystemIcon  mIconGroups.size ="+mIconGroups.size());
        mIconLogger.onIconVisibility(getSlotName(index), holder.isVisible());
        mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
    }

刚开始以为走到mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));就完了,已经把图标都初始化完了,其实不然。为什么呢?因为开机初始化的时候mIconGroups的size现在还是0哦。

D lgy_debug_systemui: StatusBarIconControllerImpl.java addSystemIcon  mIconGroups.size =0

所以到这里onIconAdded 这个方法还没执行呢。

那么问题来了,是在什么时候才执行onIconAdded的呢?其实是在addIconGroup这个方法中调用 group.onIconAdded真正的初始化icon;

SystemUI中有3个不同的地方调用到addIconGroup;

第一个是我们的锁屏UI

KeyguardstatusBarView.java--->onAttachedToWindow begin addIconGroup

D lgy_debug_systemui: StatusBarIconControllerImpl.java addIconGroup  mIconGroups.size() =1

第二个是我们的状态栏UI

CollapsedStatusBarFragment.java---》onViewCreated begin addIconGroup

D lgy_debug_systemui: StatusBarIconControllerImpl.java addIconGroup  mIconGroups.size() =2

第三个是我们的下拉快捷图标QS

QuickStatusBarHeader.java--->onAttachedToWindow begin addIconGroup

D lgy_debug_systemui: StatusBarIconControllerImpl.java addIconGroup  mIconGroups.size() =3

    @Override
    public void addIconGroup(IconManager group) {
        mIconGroups.add(group);
        android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java addIconGroup  mIconGroups.size() ="+mIconGroups.size());        
        List<Slot> allSlots = getSlots();
				android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java addIconGroup  allSlots.size() ="+allSlots.size());        
        for (int i = 0; i < allSlots.size(); i++) {
            Slot slot = allSlots.get(i);
            List<StatusBarIconHolder> holders = slot.getHolderListInViewOrder();
            boolean blocked = mIconBlacklist.contains(slot.getName());

            for (StatusBarIconHolder holder : holders) {
                int tag = holder.getTag();
                int viewIndex = getViewIndex(getSlotIndex(slot.getName()), holder.getTag());
                android.util.Log.d("lgy_debug_systemui","StatusBarIconControllerImpl.java addIconGroup  begion IconAdded ");        
                group.onIconAdded(viewIndex, slot.getName(), blocked, holder);
            }
        }
    }

 

        @Override
        protected void onIconAdded(int index, String slot, boolean blocked,
                StatusBarIconHolder holder) {
            android.util.Log.d("lgy_debug_systemui","StatusBarIconController.java--->onIconAdded 222");  
            StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
            view.setStaticDrawableColor(mColor);
            view.setDecorColor(mColor);
        }
        protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
                StatusBarIconHolder holder) {
            android.util.Log.d("lgy_debug_systemui","StatusBarIconController.java--->addHolder addHolder.getType =   "+holder.getType()); 
            android.util.Log.d("lgy_debug_systemui","StatusBarIconController.java--->addHolder slot =   "+slot);                 	
            switch (holder.getType()) {
                case TYPE_ICON:
                    return addIcon(index, slot, blocked, holder.getIcon());

                case TYPE_WIFI:
                    return addSignalIcon(index, slot, holder.getWifiState());

                case TYPE_MOBILE:
                    return addMobileIcon(index, slot, holder.getMobileState());
            }

            return null;
        }

根据holder的类型,走相对应的设置流程,蓝牙的类型为TYPE_ICON。走 addIcon(index, slot, blocked, holder.getIcon());

D lgy_debug_systemui: StatusBarIconController.java--->addHolder.getType =   0

        protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
                StatusBarIcon icon) {
            android.util.Log.d("lgy_debug_systemui","StatusBarIconController.java--->addIcon  2222");    	
            StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
            view.set(icon);
            mGroup.addView(view, index, onCreateLayoutParams());//这里的mGroup就是在CollapsedStatusBarFragment.java初始化DarkIconManager时传下去的R.id.statusIcons我们的状态栏容器StatusIconContainer
            return view;
 }

这个StatusIconContainer实现的比较简单 感兴趣的朋友,自行去看看源码。

至此 mIconController.setIcon才算初始化完成了。

 

后面状态图标的更新流程会走以下流程,以headset为例

PhoneStatusBarPolicy.java--->updateHeadsetPlug() .

StatusBarIconControllerImpl.java setIcon  slot = headset

StatusBarIconControllerImpl.java setIcon  resourceId = 2131231117

StatusBarIconControllerImpl.java setIcon  holder = com.android.systemui.statusbar.phone.StatusBarIconHolder@44079a0

handleSet(index, holder);

    private void handleSet(int index, StatusBarIconHolder holder) {
        int viewIndex = getViewIndex(index, holder.getTag());
        mIconLogger.onIconVisibility(getSlotName(index), holder.isVisible());
        mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
    }

 

        public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) {
        	  android.util.Log.d("lgy_debug_systemui","StatusBarIconController.java--->onSetIconHolder 2  holder.getType() ="+holder.getType());
            switch (holder.getType()) {
                case TYPE_ICON:
                    onSetIcon(viewIndex, holder.getIcon());
                    return;
                case TYPE_WIFI:
                    onSetSignalIcon(viewIndex, holder.getWifiState());
                    return;

                case TYPE_MOBILE:
                    onSetMobileIcon(viewIndex, holder.getMobileState());
                default:
                    break;
            }
        }
        @Override
        public void onSetIcon(int viewIndex, StatusBarIcon icon) {
        	  android.util.Log.d("lgy_debug_systemui","StatusBarIconController.java--->onSetIcon 1  "); 	
            super.onSetIcon(viewIndex, icon);
            mDarkIconDispatcher.applyDark((DarkReceiver) mGroup.getChildAt(viewIndex));
        }

 

        public void onSetIcon(int viewIndex, StatusBarIcon icon) {
        	  android.util.Log.d("lgy_debug_systemui","StatusBarIconController.java--->onSetIcon  2");
            StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex);
            view.set(icon);
        }

从父容器mGrop中通过ViewIndex获取到StatusBarIconView  这里就是我们的Headset,然后给他设置icon;

最后调用mDarkIconDispatcher.applyDark((DarkReceiver) mGroup.getChildAt(viewIndex));//给Headset图标设置颜色随背景而改变的功能

这个DarkReceiver是一个接口,其实现者是DarkIconDispatcherImpl.java

public interface DarkIconDispatcher {
 void addDarkReceiver(DarkReceiver receiver);

// Used to reapply darkness on an object, must have previously been added through
// addDarkReceiver.
 void applyDark(DarkReceiver object);
}

 

      public void addDarkReceiver(DarkReceiver receiver) {
          mReceivers.put(receiver, receiver);
          receiver.onDarkChanged(mTintArea, mDarkIntensity, mIconTint);         
      }

      public void applyDark(DarkReceiver object) {
          mReceivers.get(object).onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
      }

状态栏上的图标都可以自己实现自己的onDarkChanged方法,当背景改变时调用自己的onDarkChanged;

Systemui中有一些自定义的view已经自己实现了onDarkChanged方法并通过addDarkReceiver()方法进行注册。

BatteryMeterView.java 电池图标  

Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery);

Clock.java  时间图标

    Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);

 

本篇到此就算结束了

 

 

 

 

 

<think>好的,我现在需要回答用户关于Android 9.0隐藏下拉状态栏电池图标的源码修改位置的问题。首先,我得回忆一下Android系统UI的相关组件结构。状态栏图标管理通常是在SystemUI模块中,具体来说,电池图标可能在StatusBar模块的某个类里。 用户提到的是下拉状态栏,也就是通知栏的快捷设置部分,这里可能属于QuickSettings或类似的布局文件。不过电池状态显示通常是在状态栏的右侧,包括电池百分比和图标。在Android源码中,电池图标的管理可能由BatteryMeterView或者BatteryController来处理。 接下来,我需要确认具体的类和方法。在AOSP的SystemUI项目中,BatteryMeterView是负责绘制电池图标的视图类,位于com.android.systemui.BatteryMeterView。而控制其显示与否的可能是在StatusBarIconController或者相关的布局文件中。 另外,隐藏图标可能需要修改SystemUI的布局文件,比如status_bar.xml或类似的布局文件,将对应的BatteryMeterView的可见性设置为GONE。或者,在代码中通过findViewById获取该视图并设置Visibility为View.GONE。 还需要考虑系统设置中的相关标志位,比如是否有配置项控制电池图标的显示,可能需要在config.xml中修改默认值。不过用户的需求是直接修改源码隐藏,所以可能需要直接注释掉相关的布局或代码逻辑。 要确保修改的是正确的版本,Android 9.0对应的分支是android-9.0.0_rXX,需要确认代码路径是否正确。例如,SystemUI的代码路径通常是packages/apps/SystemUI/src/com/android/systemui/。 可能的步骤包括: 1. 找到StatusBar的布局文件,如status_bar.xml,检查是否有BatteryMeterView。 2. 如果布局中有该视图,设置android:visibility="gone"。 3. 或者在代码中,如StatusBarPhone类中,找到初始化电池图标的部分并隐藏。 4. 另外,检查BatteryController类,看是否有控制显示的逻辑,修改相关方法。 需要注意的是,直接修改布局文件可能更直接,但不同厂商的定制ROM可能会有所不同,这里假设是原生AOSP的情况。同时,修改后需要重新编译SystemUI模块并推送生效。 总结可能的修改位置: - SystemUI的res/layout/status_bar.xml - BatteryMeterView的初始化代码 - BatteryController中的状态更新逻辑</think>要隐藏Android 9.0下拉状态栏的电池显示,需要修改SystemUI模块的源码。以下是具体步骤和关键位置: ### 核心修改位置 1. **布局文件修改** ```xml <!-- 文件路径:SystemUI/res/layout/status_bar.xml --> <com.android.systemui.BatteryMeterView android:id="@+id/battery" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" /> <!-- 添加此属性隐藏电池图标 --> ``` 2. **控制逻辑修改(可选)** ```java // 文件路径:SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java protected void createStatusBarWindow() { ... mBatteryView = mStatusBarView.findViewById(R.id.battery); mBatteryView.setVisibility(View.GONE); // 强制隐藏电池视图 } ``` ### 详细操作步骤 1. **修改布局文件** - 找到`status_bar.xml`布局文件 - 给`BatteryMeterView`添加`android:visibility="gone"`属性 2. **重新编译SystemUI** ```bash make SystemUI && adb push out/target/product/{device}/system/priv-app/SystemUI/SystemUI.apk /system/priv-app/SystemUI/ ``` 3. **清除旧数据** ```bash adb shell pm clear com.android.systemui ``` ### 注意事项 1. 不同厂商ROM可能自定义了状态栏布局(如`quick_status_bar.xml`) 2. 若需保留电量百分比文字显示,需单独处理`BatteryPercentTextView` 3. Android 10+版本需修改`status_bar.xml`中的`battery_container`布局 > 完整实现需要同步修改`BatteryController`相关逻辑,防止系统异常调用隐藏的电池组件。建议通过`config.xml`添加开关控制更符合开发规范: > ```xml > <!-- SystemUI/res/values/config.xml --> > <bool name="config_showBatteryIndicator">false</bool> > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值