19年最新!研究SystemUI找到全局弹框方案

阅读之前

一、我的情况介绍

· 一枚大三学生,在实习中接到一个在电话手表的Launcher上实现全局弹框的需求,具体需求会在下面分析;
· 这算是第一次这么认真去阅读源码(要恰饭的嘛)总结了一些自己阅读源码的方法心得,也算是为和我一样第一次接触阅读源码的小伙伴铺路(一开始踩坑太多了,又不知道看哪里有用所以也会失去耐心);
注:本篇文章源码是Android7.1

二、这里有什么

  • 一个全局弹框方案(自己做了一个悬浮球,还想加闹钟功能的,正好可以用在这里)
  • 优先级可控(在底层插入)
  • 阅读源码的步骤和技巧心得
  • 对SystemUI有个系统性的了解
  • 关于锁屏一切你想知道的都有(应该有···)

三、阅读指南

· 个人建议对照我的流程图,然后自己打开源码去看
· 实在不理解的地方再看我写的源码解析,应该会帮到你
· 同时注意源码用了哪些常见技巧机制(我总结的未必全面)

超级速成法

直接看我的结论

速成法

直接看源码解析

文章目录

  • 阅读之前
    • 一、我的情况介绍
    • 二、这里有什么
    • 三、阅读指南
  • 需求分析
  • 方案分析
  • 使用Android studio源码阅读方法
  • SystemUI的大致框架
  • 锁屏的启动流程
    • 一、[流程图](https://www.edrawsoft.cn/viewer/public/s/87690642623138)
    • 二、[7.1.1锁屏的启动流程源码解析](https://blog.csdn.net/yin1031468524/article/details/56284449)
  • 锁屏为何会触发Activity的onPause
    • 一、思路提供
    • 二、[流程图](https://www.edrawsoft.cn/viewer/public/s/566dc735296192)
    • 三、[源码解析](https://blog.csdn.net/weixin_40404011/article/details/95941601)
      • KeyguardViewMediator
      • ActivityManagerNative
      • ActivityManagerService
      • ActivityStackSupervisor管理Activity堆的
      • ActivityStack
      • ApplicationThreadNative,类似于ActivityManagerNative用于联系ActivityThread
      • ActivityThread
    • 四、总结
  • 锁屏到底附着在哪里?
    • 一、[流程图](https://www.edrawsoft.cn/viewer/public/s/3e0c6491117377)
    • 二、[源码](https://blog.csdn.net/weixin_40404011/article/details/95945869)
      • 同样入口都是SystemService
      • SystemUIService到SystemUIApplication启动"服务",实际上是初始化SystemUI类
      • SystemBars关注这个类,是手机的状态栏
      • 到PhoneStatusBar这里的start
      • StatusBarKeyguardViewManager
      • KeyguardBouncer,可以看到锁屏的View是建立在解锁的View上面而解锁的View又是建立在状态栏内
      • 锁屏是建立在哪个Context上面的
      • SystemUIApplication
      • 由于KeyguardService中创建的KeyguardViewMediator得到了解释,现在看KeyguardViewMediator这个类是怎么传递Context的
      • StatusBarKeyguardViewManager,构造方法中得到了Context
      • KeyguardHostView,注意这个类的说明,这是最基本的锁屏View
      • 锁屏的View布局
    • 三、总结
  • 如何做到统一管理全局弹框
  • 源码阅读各种方法总结
    • 阅读源码前的准备
    • 借助前人的智慧
    • 总结一份源码流程图
    • 细心少走弯路
    • 资料组合和拆分
    • 学习源码技巧

需求分析

  • View的优先级易管理,不会出现闪屏(add——remove——add)
  • 统一管理所有View
  • 可以触发生命周期回调

方案分析

了解Android锁屏是怎么解决这些问题的
研究SystemUI


使用Android studio源码阅读方法

  1. 首先可以通过官方Git查看,很齐全
  2. 在AS的Sdk Manager中下载对应版本的源码
  3. 修复部分爆红源码方法

推荐AS+Git的方式查看,因为AS下载的源码好像不够全.部分被隐藏的也不能直接跳转过去
搜索类通过AS的shift+shift


SystemUI的大致框架

一定要先看一遍这个,可以少踩很多坑

大致总结一下

  • SystemUI的根视图是在PhoneStatusBar的makeStatusBarView()方法中加载的。(锁屏是个View,建立在StatusBar上)
  • SystemUI涉及顶部状态栏、下拉通知栏、底部导航栏、锁屏界面、解锁界面

锁屏的启动流程

起点果然是Zygote——SystemServer——WMS
建议自己看源码,不理解的、乱了或者想找其他需求的看流程图(非常有用)

一、流程图

二、7.1.1锁屏的启动流程源码解析

涉及的源码技巧

  • Binder跨进程通信机制(代理模式)
  • 回调函数通知多个类

锁屏为何会触发Activity的onPause

阅读源码建议:

1.明确目标
2.明确思路
3.自己看源码
4.怕走错路就看我流程图
5.实在不懂就定位我的源码解析
ps:不想太动脑的直接看源码解析

一、思路提供

思路提供:Activity的启动流程

  • startActivity(…)此方法是启动一个Activity的核心代码,ActivityManagerNative.getDefault()返回的是一个IActivityManager接口实例,它是由ActivityManagerProxy实现的。
  • startActivity()方法主要就是通过Binder机制完成了客户端向服务器端的通信,即调用mRemote.transact()方法完成通信
  • 那么客户端通过 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);告诉服务端要启动一个Activity,然后就进入AMS进程了,在服务端的AMS进程中经过一系列的调用,最后回到ActivityThread.ApplicationThread的调用流程了
  • 然后AMS说让ActivityThread来完成真正的Activity启动,然后ActivityThread就开始要准备启动一个Activity了,实际上在执行ApplicationThreadProxy的schedulePauseActivity()方法时,就是在用IPC原理远程调用ApplicationThread的schedulePauseActivity()方法,其实经过ActivityThread的内部类H(就是一个Handler),最后一步步调用到了handleLaunchActivity()方法

思路提供:AMS与ApplicationThread通信

mRemote 就是我们上面ServiceManager.getService(“activity”)返回的,也就是AMS得BinderProxy,这个BinderProxy会将ApplicationThread的binder 传递到AMS进程,那么AMS就相当于拥有了ApplicationThread得引用。那么就可以远程调用了

思路提供:锁屏的启动流程

可以确定锁屏是一个自定义View
关键与AMS交互的类是KeyguardViewMediator

结论:Activity的生命周期由ActivityThread处理——ActivityThread与AMS通信——锁屏View将想办法与AMS建立关系才能控制Activity的生命周期

二、流程图

先在这解释一下怎么看流程图,理解了后相信很清晰(懒得加箭头了····)

19年最新!研究SystemUI找到全局弹框方案_第1张图片

  • 开头字母是大写的——代表类
  • 同一列的——代表代码在同一个类中
  • 从上往下读

三、源码解析

KeyguardViewMediator

    /**
     * Handle message sent by {@link #showLocked}.
     * @see #SHOW
     */
    private void handleShow(Bundle options) {
        Trace.beginSection("KeyguardViewMediator#handleShow");
        final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
        if (mLockPatternUtils.isSecure(currentUser)) {
            mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured(currentUser);
        }
        synchronized (KeyguardViewMediator.this) {
            if (!mSystemReady) {
                if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
                return;
            } else {
                if (DEBUG) Log.d(TAG, "handleShow");
            }

            setShowingLocked(true);
            mStatusBarKeyguardViewManager.show(options);
            mHiding = false;
            mWakeAndUnlocking = false;
            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;
            updateActivityLockScreenState();//*-这里建立与AMS的连接!
            adjustStatusBarLocked();
            userActivity();//*-在这里与PowerManager建立起连接!

            mShowKeyguardWakeLock.release();
        }
        mKeyguardDisplayManager.show();
        Trace.endSection();
    }
	

    private void updateActivityLockScreenState() {
        Trace.beginSection("KeyguardViewMediator#updateActivityLockScreenState");
        try {
            ActivityManagerNative.getDefault().setLockScreenShown(mShowing, mOccluded);//这里建立与AMS连接,这个方法先由ActivityManagerNative内部类来实现
        } catch (RemoteException e) {
        }
        Trace.endSection();
    }

ActivityManagerNative

    /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();//为了获得AMS的Binder对象
    }
	
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");//与获取AMS
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
	
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);//关键是创建这个代理
    }
	
	//内部类ActivityManagerProxy
    public void setLockScreenShown(boolean showing, boolean occluded) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(showing ? 1 : 0);
        data.writeInt(occluded ? 1 : 0);
		//这里将会通知AMS执行这个方法
        mRemote.transact(SET_LOCK_SCREEN_SHOWN_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
	

ActivityManagerService

    public void setLockScreenShown(boolean showing, boolean occluded) {
        if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires permission "
                    + android.Manifest.permission.DEVICE_POWER);
        }

        synchronized(this) {
            long ident = Binder.clearCallingIdentity();
            try {
                if (DEBUG_LOCKSCREEN) logLockScreen(" showing=" + showing + " occluded=" + occluded);
                mLockScreenShown = (showing && !occluded) ? LOCK_SCREEN_SHOWN : LOCK_SCREEN_HIDDEN;
                if (showing && occluded) {
                    // The lock screen is currently showing, but is occluded by a window that can
                    // show on top of the lock screen. In this can we want to dismiss the docked
                    // stack since it will be complicated/risky to try to put the activity on top
                    // of the lock screen in the right fullscreen configuration.
                    mStackSupervisor.moveTasksToFullscreenStackLocked(DOCKED_STACK_ID,
                            mStackSupervisor.mFocusedStack.getStackId() == DOCKED_STACK_ID);
                }
				
                updateSleepIfNeededLocked();//做屏幕休眠前的准备
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }
	
	
	
    void updateSleepIfNeededLocked() {
        if (mSleeping && !shouldSleepLocked()) {
            mSleeping = false;
            startTimeTrackingFocusedActivityLocked();
            mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
            //*如果需要锁定,请退出睡眠状态.这里只是跳到PowerManager中release(用于释放亮屏锁)
            mStackSupervisor.comeOutOfSleepIfNeededLocked();
            updateOomAdjLocked();
        } else if (!mSleeping && shouldSleepLocked()) {
            mSleeping = true;
            if (mCurAppTimeTracker != null) {
                mCurAppTimeTracker.stop();
            }
            //*-这里是获取到顶层的Activity,但是在哪里用到还未知
            mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
            mStackSupervisor.goingToSleepLocked();//*-从这里出发接触ActivityThread
            updateOomAdjLocked();

            // Initialize the wake times of all processes.
            checkExcessivePowerUsageLocked(false);
            mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
            Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
            mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
        }
    }

ActivityStackSupervisor管理Activity堆的

    void goingToSleepLocked() {
        scheduleSleepTimeout();
        if (!mGoingToSleep.isHeld()) {
            mGoingToSleep.acquire();
            if (mLaunchingActivity.isHeld()) {
                if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
                    throw new IllegalStateException("Calling must be system uid");
                }
                mLaunchingActivity.release();
                mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
            }
        }
        checkReadyForSleepLocked();//检查休眠前的工作是否完成
    }
	
    void checkReadyForSleepLocked() {
        if (!mService.isSleepingOrShuttingDownLocked()) {
            // Do not care.
            return;
        }

        if (!mSleepTimeout) {
            boolean dontSleep = false;
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
					//遍历Activity任务栈来检查栈内的Activity是否做好了屏幕休眠准备
                    dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
                }
            }
       
    }

ActivityStack

    /**
     * @return true if something must be done before going to sleep.
     */
    boolean checkReadyForSleepLocked() {
	//如果还有正在Resume的Activity
        if (mResumedActivity != null) {
            // Still have something resumed; can't sleep until it is paused.
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity);
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "Sleep => pause with userLeaving=false");
					//那就去执行onPause,这么说无论是否顶层的Activity,只要是onResume的都会被执行onPause
            startPausingLocked(false, true, null, false);
            return true;
        }
        if (mPausingActivity != null) {
            // Still waiting for something to pause; can't sleep yet.
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity);
            return true;
        }

        if (hasVisibleBehindActivity()) {
            // Stop visible behind activity before going to sleep.
            final ActivityRecord r = getVisibleBehindActivity();
            mStackSupervisor.mStoppingActivities.add(r);
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Sleep still waiting to stop visible behind " + r);
            return true;
        }

        return false;
    }
	
    /**
     * Start pausing the currently resumed activity.  It is an error to call this if there
     * is already an activity being paused or there is no resumed activity.
     *
     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
     * @param uiSleeping True if this is happening with the user interface going to sleep (the
     * screen turning off).
     * @param resuming The activity we are currently trying to resume or null if this is not being
     *                 called as part of resuming the top activity, so we shouldn't try to instigate
     *                 a resume here if not null.
     * @param dontWait True if the caller does not want to wait for the pause to complete.  If
     * set to true, we will immediately complete the pause here before returning.
     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
     * it to tell us when it is done.
     */
    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean dontWait) {
			
	  //这个类会保存与Activity相关的
	  //一个ActivityRecord对应一个Activity,保存了一个Activity的所有信息;但是一个Activity可能会有多个ActivityRecord,因为Activity可以被多次启动,这个主要取决于其启动模式。
      ActivityRecord prev = mResumedActivity;
	  
      if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                //*-这里到出发去ActivityThread
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
    }

ApplicationThreadNative,类似于ActivityManagerNative用于联系ActivityThread

    public final void schedulePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(finished ? 1 : 0);
        data.writeInt(userLeaving ? 1 :0);
        data.writeInt(configChanges);
        data.writeInt(dontReport ? 1 : 0);
        mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

ActivityThread

        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            int seq = getLifecycleSeq();
            if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
                    + " operation received seq: " + seq);
            sendMessage(
					//无论发送哪条消息都会触发onPause
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
        }
		
		
		
                case PAUSE_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, false,
                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
                            (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case PAUSE_ACTIVITY_FINISHING: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
                            args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
				
				
    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
        if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
        if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
            return;
        }
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
			//执行onPause
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }
	
	
    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
        if (r.paused) {
            if (r.activity.mFinished) {
                // If we are finishing, we won't call onResume() in certain cases.
                // So here we likewise don't want to call onPause() if the activity
                // isn't resumed.
                return null;
            }
            RuntimeException e = new RuntimeException(
                    "Performing pause of activity that is not resumed: "
                    + r.intent.getComponent().toShortString());
            Slog.e(TAG, e.getMessage(), e);
        }
        if (finished) {
            r.activity.mFinished = true;
        }

        // Next have the activity save its current state and managed dialogs...
        if (!r.activity.mFinished && saveState) {
            callCallActivityOnSaveInstanceState(r);
        }
		//经过判断后确定需要执行onPause
        performPauseActivityIfNeeded(r, reason);

        // Notify any outstanding on paused listeners
        ArrayList<OnActivityPausedListener> listeners;
        synchronized (mOnPauseListeners) {
            listeners = mOnPauseListeners.remove(r.activity);
        }
        int size = (listeners != null ? listeners.size() : 0);
        for (int i = 0; i < size; i++) {
            listeners.get(i).onPaused(r.activity);
        }

        return !r.activity.mFinished && saveState ? r.state : null;
    }
				
    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        if (r.paused) {
            // You are already paused silly...
            return;
        }

        try {
            r.activity.mCalled = false;
            //*-在这里正式暂停,Instrumentation是直接管理Activity生命周期的类
            mInstrumentation.callActivityOnPause(r.activity);
            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
                    r.activity.getComponentName().getClassName(), reason);
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                        + " did not call through to super.onPause()");
            }
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException("Unable to pause activity "
                        + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
            }
        }
        r.paused = true;
    }

这里总结一下比较关键的点
要对Binder机制有一定的了解,不然会一头雾水

四、总结

  • KeyguardViewMediator中开始建立与AMS的连接
  • 建立连接前需要通过ActivityManagerNative中的代理类进程跨进程调用AMS
  • AMS管理Activity栈
  • 找到Activity栈中还在onResume的Activity
  • 获取这个Activity的ActivityThread
  • 得到ActivityThread一切好说

锁屏到底附着在哪里?

一、流程图

二、源码

参考链接

同样入口都是SystemService

[外链图片转存失败(img-aF1SRTWo-1563160697458)(/uploads/bd283f2aad12ec38ee9a08623256b2ef/image.png)]

SystemUIService到SystemUIApplication启动"服务",实际上是初始化SystemUI类

19年最新!研究SystemUI找到全局弹框方案_第2张图片

SystemBars关注这个类,是手机的状态栏

public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
    ......
    //start()方法是再启动中调用的额方法
    @Override
    public void start() {
        if (DEBUG) Log.d(TAG, "start");
        //这里会启动ServiceMonitor,并调用其的start(),重点看注释“如果没有远程服务,就会回调onNoService()方法”
        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
        mServiceMonitor.start();  // will call onNoService if no remote service is found
    }

    @Override
    public void onNoService() {
        if (DEBUG) Log.d(TAG, "onNoService");
        createStatusBarFromConfig();  // fallback to using an in-process implementation
    }
    ......
	
	//第一次启动时,远程服务没有被启动,因此会回调onNoService()方法,然后调用createStatusBarFromConfig()方法,继续
 private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        //根据xml中的配置,是一个应用包名路径,这里就是“com.android.systemui.statusbar.phone.PhoneStatusBar”
        //然后根据包名路径并启动
        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;
        //这里调用mStausBar就是“PhoneStatusBar”实例,并调用start()方法
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }
}

到PhoneStatusBar这里的start

public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        HeadsUpManager.OnHeadsUpChangedListener {

        ......
 
        @Override
        public void start() {
        ......
		
        super.start(); // calls createAndAddWindows(),在这里把状态栏的View加到WindowManager,初始化View,顶部状态栏,和底部导航栏

        ......

        addNavigationBar();

        // Lastly, call to the icon policy to install/update all the icons.
        mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController,
                mUserInfoController, mBluetoothController);
        mIconPolicy.setCurrentUserSetup(mUserSetup);

        ......
        startKeyguard(); //启动屏锁

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

    private void addStatusBarWindow() {
        makeStatusBarView();//*-这里先生成View
        mStatusBarWindowManager = new StatusBarWindowManager(mContext);
        mRemoteInputController = new RemoteInputController(mStatusBarWindowManager,
                mHeadsUpManager);
				//由这里就可知,无论是锁屏View、导航栏View、通知栏View都是基于这个状态栏ViewGroup
				//这样就避免了多个Window层级不好管理,转向好管理的ViewGroup
        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());//*-在这里加入WindowManager
    }

    /**
     * Adds the status bar view to the window manager.
     *
     * @param statusBarView The view to add.
     * @param barHeight The height of the status bar in collapsed state.
     */
    public void add(View statusBarView, int barHeight) {

        // Now that the status bar window encompasses the sliding panel and its
        // translucent backdrop, the entire thing is made TRANSLUCENT and is
        // hardware-accelerated.
        mLp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                barHeight,
                WindowManager.LayoutParams.TYPE_STATUS_BAR,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                PixelFormat.TRANSLUCENT);
        mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        mLp.gravity = Gravity.TOP;
        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
        mLp.setTitle("StatusBar");
        mLp.packageName = mContext.getPackageName();
        mStatusBarView = statusBarView;
        mBarHeight = barHeight;
        mWindowManager.addView(mStatusBarView, mLp);
        mLpChanged = new WindowManager.LayoutParams();
        mLpChanged.copyFrom(mLp);
    }
	
	
	//接下来看看锁屏View是怎么出现的
    protected void startKeyguard() {
        Trace.beginSection("PhoneStatusBar#startKeyguard");
		//关注这个类
        KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
        mFingerprintUnlockController = new FingerprintUnlockController(mContext,
                mStatusBarWindowManager, mDozeScrimController, keyguardViewMediator,
                mScrimController, this);
		//关注这个类
        mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
                getBouncerContainer(), mStatusBarWindowManager, mScrimController,
                mFingerprintUnlockController);
        mKeyguardIndicationController.setStatusBarKeyguardViewManager(
                mStatusBarKeyguardViewManager);
        mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
        mIconPolicy.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
        mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);

        mRemoteInputController.addCallback(new RemoteInputController.Callback() {
            @Override
            public void onRemoteInputSent(Entry entry) {
                if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) {
                    removeNotification(entry.key, null);
                } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) {
                    // We're currently holding onto this notification, but from the apps point of
                    // view it is already canceled, so we'll need to cancel it on the apps behalf
                    // after sending - unless the app posts an update in the mean time, so wait a
                    // bit.
                    mHandler.postDelayed(() -> {
                        if (mRemoteInputEntriesToRemoveOnCollapse.remove(entry)) {
                            removeNotification(entry.key, null);
                        }
                    }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
                }
            }
        });

        mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
        mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
        Trace.endSection();
    }
}

StatusBarKeyguardViewManager

    public void registerStatusBar(PhoneStatusBar phoneStatusBar,
            ViewGroup container, StatusBarWindowManager statusBarWindowManager,
            ScrimController scrimController,
            FingerprintUnlockController fingerprintUnlockController) {
        mPhoneStatusBar = phoneStatusBar;
		//注意这个ViewGroup,就是状态栏
        mContainer = container;
        mStatusBarWindowManager = statusBarWindowManager;
        mScrimController = scrimController;
        mFingerprintUnlockController = fingerprintUnlockController;
		//他把这个ViewGroup继续传递给解锁界面
        mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
                mViewMediatorCallback, mLockPatternUtils, mStatusBarWindowManager, container);
    }

KeyguardBouncer,可以看到锁屏的View是建立在解锁的View上面而解锁的View又是建立在状态栏内

    protected void inflateView() {
        removeView();
        mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
        mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
        mKeyguardView.setViewMediatorCallback(mCallback);
        mContainer.addView(mRoot, mContainer.getChildCount());
        mRoot.setVisibility(View.INVISIBLE);
    }

锁屏是建立在哪个Context上面的

回顾锁屏启动流程图,从KeyguardService开始,在开启这个服务的时候onCreate方法中获取了一个SystemUIApplication,这个Application是个关键

    @Override
    public void onCreate() {
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        mKeyguardViewMediator =
                ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
    }

SystemUIApplication


	//这里是指与SystemUI有关的类数组
    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,
            Divider.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,
            com.android.systemui.keyboard.KeyboardUI.class,
            com.android.systemui.tv.pip.PipUI.class,
            com.android.systemui.shortcut.ShortcutKeyDispatcher.class,
            com.android.systemui.VendorServices.class
    };
	
	

    /**
     * Hold a reference on the stuff we start.
     */
    private final SystemUI[] mServices = new SystemUI[SERVICES.length];//SystemUI集合
    private boolean mServicesStarted;
    private boolean mBootCompleted;
    private final Map<Class<?>, Object> mComponents = new HashMap<>();//注意这个HashMap
	
	
    @Override
    public void onCreate() {
        super.onCreate();
        // Set the application theme that is inherited by all services. Note that setting the
        // application theme in the manifest does only work for activities. Keep this in sync with
        // the theme set there.
        setTheme(R.style.systemui_theme);

		//这个Application在onCreate的时候把自己的Context传递给了SystemUIFactory,可以说是所有继承了SystemUI的Context的由来
        SystemUIFactory.createFromConfig(this);

        if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
            IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
            registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (mBootCompleted) return;

                    if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
                    unregisterReceiver(this);
                    mBootCompleted = true;
                    if (mServicesStarted) {
                        final int N = mServices.length;
                        for (int i = 0; i < N; i++) {
                            mServices[i].onBootCompleted();
                        }
                    }
                }
            }, filter);
        } else {
            // For a secondary user, boot-completed will never be called because it has already
            // been broadcasted on startup for the primary SystemUI process.  Instead, for
            // components which require the SystemUI component to be initialized per-user, we
            // start those components now for the current non-system user.
            startServicesIfNeeded(SERVICES_PER_USER);
        }
    }

    private void startServicesIfNeeded(Class<?>[] services) {
        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 for user " +
                Process.myUserHandle().getIdentifier() + ".");
        final int N = services.length;
        for (int i=0; i<N; i++) {
            Class<?> cl = services[i];
            if (DEBUG) Log.d(TAG, "loading: " + cl);
            try {
				//刚刚那个HashMap中的Object在这里统统实例化
                Object newService = SystemUIFactory.getInstance().createInstance(cl);
                mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InstantiationException ex) {
                throw new RuntimeException(ex);
            }
			//并且获取了Context
            mServices[i].mContext = this;
            mServices[i].mComponents = mComponents;
            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
            mServices[i].start();

            if (mBootCompleted) {
                mServices[i].onBootCompleted();
            }
        }
        mServicesStarted = true;
    }
	
	
    @SuppressWarnings("unchecked")
    public <T> T getComponent(Class<T> interfaceType) {
		//这就是Service调用的方法,通过类名得到一个已经实例化好了的类,带有Context
        return (T) mComponents.get(interfaceType);
    }

由于KeyguardService中创建的KeyguardViewMediator得到了解释,现在看KeyguardViewMediator这个类是怎么传递Context的

    private void setupLocked() {
	        mStatusBarKeyguardViewManager =
                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
                        mViewMediatorCallback, mLockPatternUtils);
	}

StatusBarKeyguardViewManager,构造方法中得到了Context

    public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
            LockPatternUtils lockPatternUtils) {
        mContext = context;
        mViewMediatorCallback = callback;
        mLockPatternUtils = lockPatternUtils;
    }
	
	
    public void registerStatusBar(PhoneStatusBar phoneStatusBar,
            ViewGroup container, StatusBarWindowManager statusBarWindowManager,
            ScrimController scrimController,
            FingerprintUnlockController fingerprintUnlockController) {
        mPhoneStatusBar = phoneStatusBar;
        mContainer = container;
        mStatusBarWindowManager = statusBarWindowManager;
        mScrimController = scrimController;
        mFingerprintUnlockController = fingerprintUnlockController;
		//流程图中的解锁界面同理
        mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
                mViewMediatorCallback, mLockPatternUtils, mStatusBarWindowManager, container);
    }

KeyguardHostView,注意这个类的说明,这是最基本的锁屏View

/**
 * Base class for keyguard view.  {@link #reset} is where you should
 * reset the state of your view.  Use the {@link KeyguardViewCallback} via
 * {@link #getCallback()} to send information back (such as poking the wake lock,
 * or finishing the keyguard).
 *
 * Handles intercepting of media keys that still work when the keyguard is
 * showing.
 */

锁屏的View布局

19年最新!研究SystemUI找到全局弹框方案_第3张图片

19年最新!研究SystemUI找到全局弹框方案_第4张图片

涉及技巧

  • 类加载器加载指定路径上的类

三、总结

原来锁屏的View是附着在状态栏的View中的
这个状态栏的View也是基本整个SystemUI的基View,通过WindowManager显示在手机上置于最上层
以基View为ViewGroup,锁屏,导航栏等View通过ViewGroup的addView方式加入,可以方便的控制插入位置即View 的优先级
View的Context源于SystemUIApplication


如何做到统一管理全局弹框

  • 使用WindowManager管理一个基View,其他View作为子View插入
  • 弹框时触发生命周期回调配合AMS、ActivityStack、ActivityThread
  • 使用RemoteViews接收其他进程的View

源码阅读各种方法总结

阅读源码前的准备

工欲善其事必先利其器,一开始我是通过Git的Find File方法找的源码,跳转非常麻烦,效率低下
后面使用AS可以直接搜索+ctrl点击跳转.方便了很多


借助前人的智慧

时间宝贵,先找找有没有相关可借鉴的资料,让自己对想了解的源码快速入门有个大致框架,可以少走弯路


总结一份源码流程图

自己阅读源码或者借助他人智慧走通之后,总结一份流程图,对查缺补漏、及时回头、清理思路或者其他扩展有非常大的帮助


细心少走弯路

一开始看那边介绍SystemUI框架的文章时没有细心···结果走了很多弯路
源码阅读对新手来说太多未知的地方了,很多你觉得没用反而可能是最关键的代码.所以一定要细心耐心


资料组合和拆分

· 面对源码中一大堆的方法、类,很容易迷失自己或者是找不到方向,也会因为部分知识基础缺失而导致一头雾水的情况(比如不了解Binder机制几乎就看不到锁屏调用onPause的关键点在哪里)
· 这时候就要拆分问题(结构化思维):锁屏能调用Activity的回调——ActivityThread控制Activity的生命周期——AMS管理Activity(这是我本来就知道的知识),那么我就去了解Activity的启动流程.打通了这条线后,再去看锁屏哪里与AMS建立的连接,这时候又出现了Binder拦路虎,再打通Binder路线后,就可以将锁屏、AMS、Activity连接起来了(组合)


学习源码技巧

这次的源码中多次出现跨进程通信的操作
类加载器的使用
一个接口多处回调的例子看第五点


你可能感兴趣的:(Android理论类,Android源码)