Quantcast
Channel: Gityuan
Viewing all 119 articles
Browse latest View live

SurfaceFlinger原理(一)

$
0
0

基于Android 6.0源码, 分析SurfaceFlinger原理

frameworks/native/services/surfaceflinger/
  - main_surfaceflinger.cpp
  - SurfaceFlinger.cpp
  - DispSync.cpp
  - MessageQueue.cpp
  - DisplayHardware/HWComposer.cpp
  
frameworks/native/libs/gui/
  - DisplayEventReceiver.cpp
  - BitTube.cpp

一. 概述

Android系统的图形处理相关的模块,就不得不提surfaceflinger,这是由init进程所启动的 守护进程,在init.rc中该服务如下:

service surfaceflinger /system/bin/surfaceflinger
    class core
    user system
    group graphics drmrpc
    onrestart restart zygote
    writepid /dev/cpuset/system-background/tasks

surfaceflinger服务属于核心类(core class),另外,当surfaceflinger重启时会触发zygote的重启。 surfaceflinger服务启动的起点便是如下的main()函数。

二. 启动过程

2.1 main

[-> main_surfaceflinger.cpp]

int main(int, char**) {
    ProcessState::self()->setThreadPoolMaxThreadCount(4);

    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();

    //实例化surfaceflinger【见小节2.2】
    sp<SurfaceFlinger> flinger =  new SurfaceFlinger();

    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
    set_sched_policy(0, SP_FOREGROUND);

    //初始化【见小节2.3】
    flinger->init();

    //发布surface flinger,注册到Service Manager
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

    // 运行在当前线程【见小节2.11】
    flinger->run();

    return 0;
}

该方法的主要功能:

  • 设定surfaceflinger进程的binder线程池个数上限为4,并启动binder线程池;
  • 创建SurfaceFlinger对象;【见小节2.1】
  • 设置surfaceflinger进程为高优先级以及前台调度策略;
  • 初始化SurfaceFlinger;【见小节2.3】
  • 将”SurfaceFlinger”服务注册到Service Manager;
  • 在当前主线程执行SurfaceFlinger的run方法。【见小节2.11】

2.2 创建SurfaceFlinger

[-> SurfaceFlinger.cpp]

SurfaceFlinger::SurfaceFlinger()
    :   BnSurfaceComposer(),
        mTransactionFlags(0),
        mTransactionPending(false),
        mAnimTransactionPending(false),
        mLayersRemoved(false),
        mRepaintEverything(0),
        mRenderEngine(NULL),
        mBootTime(systemTime()),
        mVisibleRegionsDirty(false),
        mHwWorkListDirty(false),
        mAnimCompositionPending(false),
        mDebugRegion(0),
        mDebugDDMS(0),
        mDebugDisableHWC(0),
        mDebugDisableTransformHint(0),
        mDebugInSwapBuffers(0),
        mLastSwapBufferTime(0),
        mDebugInTransaction(0),
        mLastTransactionTime(0),
        mBootFinished(false),
        mForceFullDamage(false),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mDaltonize(false),
        mHasColorMatrix(false),
        mHasPoweredOff(false),
        mFrameBuckets(),
        mTotalTime(0),
        mLastSwapTime(0)
{
    ALOGI("SurfaceFlinger is starting");
    char value[PROPERTY_VALUE_MAX];

    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
    mGpuToCpuSupported = !atoi(value);

    property_get("debug.sf.showupdates", value, "0");
    mDebugRegion = atoi(value);

    property_get("debug.sf.ddms", value, "0");
    mDebugDDMS = atoi(value);       
}

SurfaceFlinger继承于BnSurfaceComposer,IBinder::DeathRecipient,HWComposer::EventHandler

flinger的数据类型为sp强指针类型,当首次被强指针引用时则执行OnFirstRef()

2.2.1 SF.onFirstRef

void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

2.2.2 MQ.init

[-> MessageQueue.cpp]

void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this); //【见小节2.2.3】
}

这个Handler是MessageQueue的内部类Handler,此处传递的*this便是MessageQueue本身。

2.2.3 MQ.Handler

[-> MessageQueue.cpp]

class MessageQueue {
    class Handler : public MessageHandler {
        enum {
            eventMaskInvalidate     = 0x1,
            eventMaskRefresh        = 0x2,
            eventMaskTransaction    = 0x4
        };
        MessageQueue& mQueue;
        int32_t mEventMask;
    public:
        Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
        virtual void handleMessage(const Message& message);
        void dispatchRefresh();
        void dispatchInvalidate();
        void dispatchTransaction();
    };
    ...
}

2.3 SF.init

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::init() {
    Mutex::Autolock _l(mStateLock);

    //初始化EGL,作为默认的显示
    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(mEGLDisplay, NULL, NULL);

    // 初始化硬件composer对象【见小节2.4】
    mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this));

    //获取RenderEngine引擎
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

    //检索创建的EGL上下文
    mEGLContext = mRenderEngine->getEGLContext();

    //初始化非虚拟显示屏【见小节2.5】
    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
        //建立已连接的显示设备
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];

            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            //创建BufferQueue的生产者和消费者
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());

            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            //创建显示设备
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);
        }
    }

    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

    //当应用和sf的vsync偏移量一致时,则只创建一个EventThread线程
    if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) {
        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                vsyncPhaseOffsetNs, true, "app");
        mEventThread = new EventThread(vsyncSrc);
        sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                sfVsyncPhaseOffsetNs, true, "sf");
        mSFEventThread = new EventThread(sfVsyncSrc);
        mEventQueue.setEventThread(mSFEventThread);
    } else {
        //创建DispSyncSource对象【2.6】
        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                vsyncPhaseOffsetNs, true, "sf-app");
        //创建线程EventThread 【见小节2.7】
        mEventThread = new EventThread(vsyncSrc);
        //设置EventThread 【见小节2.8】
        mEventQueue.setEventThread(mEventThread);
    }

    //【见小节2.9】
    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

    //当不存在HWComposer时,则设置软件vsync
    if (mHwc->initCheck() != NO_ERROR) {
        mPrimaryDispSync.setPeriod(16666667);
    }

    //初始化绘图状态
    mDrawingState = mCurrentState;

    //初始化显示设备
    initializeDisplays();

    //启动开机动画【2.10】
    startBootAnim();
}

主要功能:

  • 初始化EGL相关;
  • 创建HWComposer对象;
  • 初始化非虚拟显示屏;
  • 启动app和sf两个EventThread线程;
  • 启动开机动画;

另外,当应用和sf的vsync偏移量一致时,则只创建一个EventThread线程;否则会创建两个DispSyncSource对象,分别是用于绘制(app)和合成(SurfaceFlinger)。

2.4 创建HWComposer

[-> HWComposer.cpp]

HWComposer::HWComposer(
        const sp<SurfaceFlinger>& flinger,
        EventHandler& handler)
    : mFlinger(flinger),
      mFbDev(0), mHwc(0), mNumDisplays(1),
      mCBContext(new cb_context),
      mEventHandler(handler),
      mDebugForceFakeVSync(false)
{
    ...
    bool needVSyncThread = true;
    int fberr = loadFbHalModule(); //加载framebuffer的HAL层模块
    loadHwcModule(); //加载HWComposer模块

    //标记已分配的display ID
    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
        mAllocatedDisplayIDs.markBit(i);
    }

    if (mHwc) {
        if (mHwc->registerProcs) {
            mCBContext->hwc = this;
            mCBContext->procs.invalidate = &hook_invalidate;
            //VSYNC信号的回调方法
            mCBContext->procs.vsync = &hook_vsync;
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                mCBContext->procs.hotplug = &hook_hotplug;
            else
                mCBContext->procs.hotplug = NULL;
            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
            //注册回调函数
            mHwc->registerProcs(mHwc, &mCBContext->procs);
        }

        //进入此处,说明已成功打开硬件composer设备,则不再需要vsync线程
        needVSyncThread = false;
        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
        ...
    }
    ...

    if (needVSyncThread) {
        //不支持硬件的VSYNC,则会创建线程来模拟定时VSYNC信号
        mVSyncThread = new VSyncThread(*this);
    }
}

HWComposer代表着硬件显示设备,注册了VSYNC信号的回调。VSYNC信号本身是由显示驱动产生的, 在不支持硬件的VSYNC,则会创建“VSyncThread”线程来模拟定时VSYNC信号。

2.5 显示设备

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::init() {
    ...
    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
        //建立已连接的显示设备
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];

            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            //创建BufferQueue的生产者和消费者
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());

            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            //创建显示设备
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);
        }
    }
    ...
}

创建IGraphicBufferProducer和IGraphicBufferConsumer,以及FramebufferSurface,DisplayDevice对象。另外, 显示设备有3类:主设备,扩展设备,虚拟设备。其中前两个都是内置显示设备,故NUM_BUILTIN_DISPLAY_TYPES=2,

2.6 DispSyncSource

[-> SurfaceFlinger.cpp]

class DispSyncSource : public VSyncSource, private DispSync::Callback {
  DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
      const char* label) :
          mValue(0),
          mTraceVsync(traceVsync),
          mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
          mVsyncEventLabel(String8::format("VSYNC-%s", label)),
          mDispSync(dispSync),
          mCallbackMutex(),
          mCallback(),
          mVsyncMutex(),
          mPhaseOffset(phaseOffset),
          mEnabled(false) {}
  ...   }

2.7 EventThread线程

[-> EventThread.cpp]

EventThread::EventThread(const sp<VSyncSource>& src)
    : mVSyncSource(src),
      mUseSoftwareVSync(false),
      mVsyncEnabled(false),
      mDebugVsyncEnabled(false),
      mVsyncHintSent(false) {

    for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
        mVSyncEvent[i].header.id = 0;
        mVSyncEvent[i].header.timestamp = 0;
        mVSyncEvent[i].vsync.count =  0;
    }
    struct sigevent se;
    se.sigev_notify = SIGEV_THREAD;
    se.sigev_value.sival_ptr = this;
    se.sigev_notify_function = vsyncOffCallback;
    se.sigev_notify_attributes = NULL;
    timer_create(CLOCK_MONOTONIC, &se, &mTimerId);
}

EventThread继承于Thread和VSyncSource::Callback两个类。

2.7.1 ET.onFirstRef

[-> EventThread.cpp]

void EventThread::onFirstRef() {
    //运行EventThread线程【见小节2.7.2】
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}

2.7.2 ET.threadLoop

[-> EventThread.cpp]

bool EventThread::threadLoop() {
    DisplayEventReceiver::Event event;
    Vector< sp<EventThread::Connection> > signalConnections;
    // 等待事件【见小节2.7.3】
    signalConnections = waitForEvent(&event); 

    //分发事件给所有的监听者
    const size_t count = signalConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        const sp<Connection>& conn(signalConnections[i]);
        //传递事件【见小节3.10】
        status_t err = conn->postEvent(event);
        if (err == -EAGAIN || err == -EWOULDBLOCK) {
            //可能此时connection已满,则直接抛弃事件
            ALOGW("EventThread: dropping event (%08x) for connection %p",
                    event.header.type, conn.get());
        } else if (err < 0) {
            //发生致命错误,则清理该连接
            removeDisplayEventConnection(signalConnections[i]);
        }
    }
    return true;
}

2.7.3 waitForEvent

[-> EventThread.cpp]

Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
        DisplayEventReceiver::Event* event)
{
    Mutex::Autolock _l(mLock);
    Vector< sp<EventThread::Connection> > signalConnections;

    do {
        bool eventPending = false;
        bool waitForVSync = false;

        size_t vsyncCount = 0;
        nsecs_t timestamp = 0;
        for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
            timestamp = mVSyncEvent[i].header.timestamp;
            if (timestamp) {
                *event = mVSyncEvent[i];
                mVSyncEvent[i].header.timestamp = 0;
                vsyncCount = mVSyncEvent[i].vsync.count;
                break;
            }
        }

        if (!timestamp) {
            //没有vsync事件,则查看其它事件
            eventPending = !mPendingEvents.isEmpty();
            if (eventPending) {
                //存在其它事件可用于分发
                *event = mPendingEvents[0];
                mPendingEvents.removeAt(0);
            }
        }

        //查找正在等待事件的连接
        size_t count = mDisplayEventConnections.size();
        for (size_t i=0 ; i<count ; i++) {
            sp<Connection> connection(mDisplayEventConnections[i].promote());
            if (connection != NULL) {
                bool added = false;
                if (connection->count >= 0) {
                    //需要vsync事件,由于至少存在一个连接正在等待vsync
                    waitForVSync = true;
                    if (timestamp) {
                        if (connection->count == 0) {
                            connection->count = -1;
                            signalConnections.add(connection);
                            added = true;
                        } else if (connection->count == 1 ||
                                (vsyncCount % connection->count) == 0) {
                            signalConnections.add(connection);
                            added = true;
                        }
                    }
                }

                if (eventPending && !timestamp && !added) {
                    //没有vsync事件需要处理(timestamp==0),但存在pending消息
                    signalConnections.add(connection);
                }
            } else {
                //该连接已死亡,则直接清理
                mDisplayEventConnections.removeAt(i);
                --i; --count;
            }
        }

        if (timestamp && !waitForVSync) {
            //接收到VSYNC,但没有client需要它,则直接关闭VSYNC
            disableVSyncLocked();
        } else if (!timestamp && waitForVSync) {
            //至少存在一个client,则需要使能VSYNC
            enableVSyncLocked();
        }

        if (!timestamp && !eventPending) {
            if (waitForVSync) {
                bool softwareSync = mUseSoftwareVSync;
                nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
                if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
                    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
                    mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
                    mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                    mVSyncEvent[0].vsync.count++;
                }
            } else {
                //不存在对vsync感兴趣的连接,即将要进入休眠
                mCondition.wait(mLock);
            }
        }
    } while (signalConnections.isEmpty());

    //到此处,则保证存在timestamp以及连接
    return signalConnections;
}

EventThread线程,进入mCondition的wait()方法,等待唤醒。

2.8 setEventThread

[-> MessageQueue.cpp]

void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
    mEventThread = eventThread;
    //创建连接
    mEvents = eventThread->createEventConnection();
    //获取BitTube对象
    mEventTube = mEvents->getDataChannel();
    //监听BitTube,一旦有数据到来则调用cb_eventReceiver()
    mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT,
            MessageQueue::cb_eventReceiver, this);
}

此处mEvents的数据类型为sp,mEventTube的数据类型为sp

2.9 EventControlThread线程

[-> EventControlThread.cpp]

EventControlThread::EventControlThread(const sp<SurfaceFlinger>& flinger):
        mFlinger(flinger),
        mVsyncEnabled(false) {
}

bool EventControlThread::threadLoop() {
    Mutex::Autolock lock(mMutex);
    bool vsyncEnabled = mVsyncEnabled;

    mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
            mVsyncEnabled);

    while (true) {
        status_t err = mCond.wait(mMutex);
        ...
        
        if (vsyncEnabled != mVsyncEnabled) {
            mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
                    SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
            vsyncEnabled = mVsyncEnabled;
        }
    }

    return false;
}

EventControlThread也是继承于Thread。

2.10 startBootAnim

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::startBootAnim() {
    property_set("service.bootanim.exit", "0");
    property_set("ctl.start", "bootanim");
}

通过控制ctl.start属性,设置成bootanim值,则触发init进程来创建开机动画进程bootanim, 到此,则开始显示开机过程的动画。 从小节[2.4 ~2.9]都是介绍SurfaceFlinger的init()过程, 紧接着便执行其run()方法。

2.11 SF.run

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::run() {
    do {
        //不断循环地等待事件【见小节2.12】
        waitForEvent(); 
    } while (true);
}

2.12 SF.waitForEvent

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::waitForEvent() {
    mEventQueue.waitMessage(); //【2.13】
}

mEventQueue的数据类型为MessageQueue。

2.13 MQ.waitMessage

[-> MessageQueue.cpp]

void MessageQueue::waitMessage() {
    do {
        IPCThreadState::self()->flushCommands();
        int32_t ret = mLooper->pollOnce(-1);
        ...
    } while (true);
}

可见SurfaceFlinger主线程进入waitMessage来等待消息的到来。

三. Vsync信号

HWComposer对象创建过程,会注册一些回调方法,当硬件产生VSYNC信号时,则会回调hook_vsync()方法。

3.1 HWC.hook_vsync

[-> HWComposer.cpp]

void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
        int64_t timestamp) {
    cb_context* ctx = reinterpret_cast<cb_context*>(
            const_cast<hwc_procs_t*>(procs));
    ctx->hwc->vsync(disp, timestamp); //【见小节3.2】
}

3.2 HWC.vsync

[-> HWComposer.cpp]

void HWComposer::vsync(int disp, int64_t timestamp) {
    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
        {
            Mutex::Autolock _l(mLock);
            if (timestamp == mLastHwVSync[disp]) {
                return; //忽略重复的VSYNC信号
            }
            mLastHwVSync[disp] = timestamp;
        }
        //【见小节3.3】
        mEventHandler.onVSyncReceived(disp, timestamp);
    }
}

当收到VSYNC信号则会回调EventHandler的onVSyncReceived()方法,此处mEventHandler是指SurfaceFlinger对象。

3.3 SF.onVSyncReceived

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
    bool needsHwVsync = false;

    {
        Mutex::Autolock _l(mHWVsyncLock);
        if (type == 0 && mPrimaryHWVsyncEnabled) {
            // 此处mPrimaryDispSync为DispSync类【见小节3.4】
            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
        }
    }

    if (needsHwVsync) {
        enableHardwareVsync();
    } else {
        disableHardwareVsync(false);
    }
}

3.4 DS.addResyncSample

此处调用addResyncSample对象的addResyncSample方法,那么先来看看DispSync对象的初始化过程

3.4.1 创建DispSync

[-> DispSync.cpp]

DispSync::DispSync() :
        mRefreshSkipCount(0),
        mThread(new DispSyncThread()) {
    //【见小节3.4.2】
    mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);

    reset();
    beginResync();
    ...
}

3.4.2 DispSyncThread线程

[-> DispSync.cpp]

virtual bool threadLoop() {
     status_t err;
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
     nsecs_t nextEventTime = 0;

     while (true) {
         Vector<CallbackInvocation> callbackInvocations;

         nsecs_t targetTime = 0;
         { // Scope for lock
             Mutex::Autolock lock(mMutex);
             if (mStop) {
                 return false;
             }

             if (mPeriod == 0) {
                 err = mCond.wait(mMutex);
                 continue;
             }

             nextEventTime = computeNextEventTimeLocked(now);
             targetTime = nextEventTime;
             bool isWakeup = false;

             if (now < targetTime) {
                 err = mCond.waitRelative(mMutex, targetTime - now);
                 if (err == TIMED_OUT) {
                     isWakeup = true;
                 } else if (err != NO_ERROR) {
                     return false;
                 }
             }

             now = systemTime(SYSTEM_TIME_MONOTONIC);

             if (isWakeup) {
                 mWakeupLatency = ((mWakeupLatency * 63) +
                         (now - targetTime)) / 64;
                 if (mWakeupLatency > 500000) {
                     mWakeupLatency = 500000;
                 }
             }
             //收集vsync信号的所有回调方法
             callbackInvocations = gatherCallbackInvocationsLocked(now);
         }

         if (callbackInvocations.size() > 0) {
             //回调所有对象的onDispSyncEvent方法
             fireCallbackInvocations(callbackInvocations);
         }
     }

     return false;
 }   

线程”DispSync”停留在mCond的wait()过程,等待被唤醒。

3.4.3 addResyncSample

[-> DispSync.cpp]

bool DispSync::addResyncSample(nsecs_t timestamp) {
    Mutex::Autolock lock(mMutex);

    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
    mResyncSamples[idx] = timestamp;

    if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
        mNumResyncSamples++;
    } else {
        mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
    }

    updateModelLocked(); //【见小节3.5】

    if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {
        resetErrorLocked();
    }

    if (kIgnorePresentFences) {
        return mThread->hasAnyEventListeners();
    }

    return mPeriod == 0 || mError > kErrorThreshold;
}

3.5 DS.updateModelLocked

[-> DispSync.cpp]

void DispSync::updateModelLocked() {
    ...
    //【见小节3.6】
    mThread->updateModel(mPeriod, mPhase);
}

3.6 DST.updateModel

[-> DispSyncThread.cpp]

class DispSyncThread: public Thread {
    void updateModel(nsecs_t period, nsecs_t phase) {
        Mutex::Autolock lock(mMutex);
        mPeriod = period;
        mPhase = phase;
        mCond.signal(); //唤醒目标线程
    }
}

唤醒DispSyncThread线程,接下里进入DispSyncThread线程。

3.7 DispSyncThread线程

[-> DispSync.cpp]

virtual bool threadLoop() {
     ...
     while (true) {
         Vector<CallbackInvocation> callbackInvocations;

         nsecs_t targetTime = 0;
         { // Scope for lock
             Mutex::Autolock lock(mMutex);
            ...
             if (now < targetTime) {
                 err = mCond.waitRelative(mMutex, targetTime - now);
                 ...
             }
             ...
             //收集vsync信号的所有回调方法
             callbackInvocations = gatherCallbackInvocationsLocked(now);
         }

         if (callbackInvocations.size() > 0) {
             //回调所有对象的onDispSyncEvent方法 【见小节3.7.1】
             fireCallbackInvocations(callbackInvocations);
         }
     }

     return false;
 } 

3.7.1 fireCallbackInvocations

void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
    for (size_t i = 0; i < callbacks.size(); i++) {
        //【见小节3.8】
        callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
    }
}

在前面小节【2.3】SurfaceFlinger调用init()的过程,创建过DispSyncSource对象。接下里便是回调该对象的 onDispSyncEvent。

3.8 DSS.onDispSyncEvent

[-> SurfaceFlinger.cpp ::DispSyncSource]

virtual void onDispSyncEvent(nsecs_t when) {
    sp<VSyncSource::Callback> callback;
    {
       Mutex::Autolock lock(mCallbackMutex);
       callback = mCallback;
    }

    if (callback != NULL) {
      callback->onVSyncEvent(when); //【见小节3.9】
    }
}

3.9 ET.onVSyncEvent

[-> EventThread.java]

void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    mVSyncEvent[0].header.id = 0;
    mVSyncEvent[0].header.timestamp = timestamp;
    mVSyncEvent[0].vsync.count++;
    mCondition.broadcast(); //唤醒EventThread线程
}

mCondition.broadcast能够唤醒处理waitForEvent()过程的EventThread【见小节2.7.2】,并往下执行conn的postEvent().

3.10 ET.postEvent

[-> EventThread.java]

status_t EventThread::Connection::postEvent(
        const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}

3.11 DER.sendEvents

[-> DisplayEventReceiver.cpp]

ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
        Event const* events, size_t count)
{
    return BitTube::sendObjects(dataChannel, events, count);
}

根据小节【2.8】可知监听BitTube,此处调用BitTube来sendObjects。一旦收到数据,则调用MQ.cb_eventReceiver()方法。

3.11.1 MQ.cb_eventReceiver

[-> MessageQueue.cpp]

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
    return queue->eventReceiver(fd, events);
}

3.11.2 MQ.eventReceiver

[-> MessageQueue.cpp]

int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
        for (int i=0 ; i<n ; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
#if INVALIDATE_ON_VSYNC
                mHandler->dispatchInvalidate();
#else
                mHandler->dispatchRefresh(); //【见小节3.12】
#endif
                break;
            }
        }
    }
    return 1;
}

3.12 MQ.dispatchRefresh

void MessageQueue::Handler::dispatchRefresh() {
    if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
        //发送消息,则进入handleMessage过程【见小节3.13】
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
    }
}

3.13 MQ.handleMessage

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);//【见小节3.14】
            break;
        case TRANSACTION:
            android_atomic_and(~eventMaskTransaction, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}

对于REFRESH操作,则进入onMessageReceived().

3.14 SF.onMessageReceived

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::TRANSACTION: {
            handleMessageTransaction();
            break;
        }
        case MessageQueue::INVALIDATE: {
            bool refreshNeeded = handleMessageTransaction();
            refreshNeeded |= handleMessageInvalidate();
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                signalRefresh();
            }
            break;
        }
        case MessageQueue::REFRESH: {
            handleMessageRefresh();
            break;
        }
    }
}

3.15 SF.handleMessageRefresh

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();
    preComposition();
    rebuildLayerStacks();
    setUpHWComposer();
    doDebugFlashRegions();
    doComposition();
    postComposition();
}

下一篇文章,再来介绍图形输出过程。

四 总结

前面讲述过程中所涉及到的线程情况:

  • 主线程“/system/bin/surfaceflinger”: 主线程
  • 线程”EventThread”:EventThread
  • 线程”EventControl”: EventControlThread
  • 线程”DispSync”:DispSyncThread

Vsync处理流程图:点击查看大图

vsync

  1. 底层vsync信号发送过来,一路执行到【小节3.6】DispSyncThread.updateModel()方法中调用mCond.signal() 来唤醒DispSyncThread线程;
  2. DispSyncThread线程:执行到【小节3.9】EventThread::onVSyncEvent()方法中调用mCondition.broadcast() 唤醒EventThread线程;
  3. EventThread线程:执行到【小节3.11】DisplayEventReceiver::sendEvents()方法中调用BitTube::sendObjects(); 由【小节2.8】可知当收到数据则调用MQ.cb_eventReceiver(),然后再经过handler消息机制,进入SurfaceFlinger主线程; 4.SurfaceFlinger主线程:【小节3.13】进入到MesageQueue的handleMessage(),最终调用SurfaceFlinger的handleMessageRefresh()。

SurfaceFlinger原理(二)

$
0
0

基于Android 6.0源码, 分析SurfaceFlinger原理

frameworks/native/services/surfaceflinger
    - Layer.cpp
    - Client.cpp

一. 图形显示输出

上一篇文章SurfaceFlinger原理(一),介绍了SurfaceFlinger和VSync的处理流程。当SurfaceFlinger进程收到VSync信号后经层层调用, 最终调用到该对象的handleMessageRefresh()方法。接下来,从该方法说起。

1.1 SF.handleMessageRefresh

[-> SurfaceFlinger.cpp]

void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();
    preComposition(); //【见小节2.1】
    rebuildLayerStacks(); //【见小节3.1】
    setUpHWComposer(); //【见小节4.1】
    doDebugFlashRegions(); 
    doComposition(); //【见小节5.1】
    postComposition(); //【见小节6.1】
}

先来看看SurfaceFlinger主线程绘制的systrace图:点击查看大图

systrace_sf

二. preComposition

2.1 preComposition

void SurfaceFlinger::preComposition()
{
    bool needExtraInvalidate = false;
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    const size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
        //回调每个图层onPreComposition方法【见小节2.2】
        if (layers[i]->onPreComposition()) {
            needExtraInvalidate = true;
        }
    }
    
    //当存在图层有变化,则发送invalidate消息
    if (needExtraInvalidate) {
        signalLayerUpdate(); //【见小节2.3】
    }
}

此处mDrawingState结构体如下:

struct State {
    //所有参与绘制的Layer图层
    LayerVector layersSortedByZ; 
    //所有输出设备的对象
    DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
};

SurfaceFlinger可以控制某些Layer不参与绘制过程,比如需要将悬浮按钮图层隐藏。

2.2 onPreComposition

[-> Layer.cpp]

bool Layer::onPreComposition() {
    mRefreshPending = false;
    return mQueuedFrames > 0 || mSidebandStreamChanged;
}

mQueuedFrames初始化值为零,当其大于零则代表图层发生变化。那么onFrameAvailable时会对 mQueuedFrames执行加1操作。

2.2.1 onFrameAvailable

[-> Layer.cpp]

void Layer::onFrameAvailable(const BufferItem& item) {
    { // Autolock scope
        Mutex::Autolock lock(mQueueItemLock);

        if (item.mFrameNumber == 1) {
            mLastFrameNumberReceived = 0;
        }

        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
                    ms2ns(500));
        }

        mQueueItems.push_back(item);
        android_atomic_inc(&mQueuedFrames); //加1操作

        //唤醒所有pending的回调方法
        mLastFrameNumberReceived = item.mFrameNumber;
        mQueueItemCondition.broadcast();
    }

    mFlinger->signalLayerUpdate(); //【见小节2.3】
}

2.3 signalLayerUpdate

void SurfaceFlinger::signalLayerUpdate() {
    mEventQueue.invalidate();
}

2.3.1 invalidate

[-> MessageQueue.cpp]

void MessageQueue::invalidate() {
#if INVALIDATE_ON_VSYNC
    mEvents->requestNextVsync();
#else
    mHandler->dispatchInvalidate();
#endif
}

2.3.2 dispatchInvalidate

void MessageQueue::Handler::dispatchInvalidate() {
    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
    }
}

发送消息到MessageQueue队列,Looper遍历消息后回调handleMessage方法来处理消息。

2.3.3 handleMessage

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case TRANSACTION:
            android_atomic_and(~eventMaskTransaction, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}

2.3.4 SF.onMessageReceived

void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::TRANSACTION: {
            handleMessageTransaction();
            break;
        }
        case MessageQueue::INVALIDATE: {
            //【见小节2.4】
            bool refreshNeeded = handleMessageTransaction();
            //【见小节2.5】
            refreshNeeded |= handleMessageInvalidate();
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                signalRefresh(); //【见小节2.6】
            }
            break;
        }
        case MessageQueue::REFRESH: {
            handleMessageRefresh();
            break;
        }
    }
}

当收到消息INVALIDATE时,则执行:

  1. handleMessageTransaction;
  2. handleMessageInvalidate;
  3. 根据是否需要刷新,来决定是否执行signalRefresh。

2.4 handleMessageTransaction

bool SurfaceFlinger::handleMessageTransaction() {
    uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
    if (transactionFlags) {
        handleTransaction(transactionFlags); //【见小节2.4.1】
        return true;
    }
    return false;
}

2.4.1 SF.handleTransaction

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
    State drawingState(mDrawingState);

    Mutex::Autolock _l(mStateLock);
    const nsecs_t now = systemTime();
    mDebugInTransaction = now;

    transactionFlags = getTransactionFlags(eTransactionMask);
    handleTransactionLocked(transactionFlags); //【见小节2.4.2】

    mLastTransactionTime = systemTime() - now;
    mDebugInTransaction = 0;
    //设置mHwWorkListDirty=true
    invalidateHwcGeometry();
}

2.4.2 SF.handleTransactionLocked

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
    const size_t count = currentLayers.size();

    //遍历所有Layer来执行其doTransaction方法
    if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue; //layer标志未改变则继续
            //【见小节2.4.3】
            const uint32_t flags = layer->doTransaction(0);
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true; //Layer成为可见,需更新
        }
    }

    // 处理显示设备的改变
    if (transactionFlags & eDisplayTransactionNeeded) {
        //当前显示设备状态的列表
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
        //之前使用过的显示设备状态的列表
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
        if (!curr.isIdenticalTo(draw)) {
            mVisibleRegionsDirty = true;
            const size_t cc = curr.size();
                  size_t dc = draw.size();

            for (size_t i=0 ; i<dc ; i++) {
                const ssize_t j = curr.indexOfKey(draw.keyAt(i));
                if (j < 0) {
                    if (!draw[i].isMainDisplay()) {
                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
                        defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
                        sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
                        if (hw != NULL)
                            hw->disconnect(getHwComposer());
                        if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
                            mEventThread->onHotplugReceived(draw[i].type, false);
                        mDisplays.removeItem(draw.keyAt(i));
                    }
                } else {
                    const DisplayDeviceState& state(curr[j]);
                    const wp<IBinder>& display(curr.keyAt(j));
                    const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
                    const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
                    if (state_binder != draw_binder) {
                        sp<DisplayDevice> hw(getDisplayDevice(display));
                        if (hw != NULL)
                            hw->disconnect(getHwComposer());
                        mDisplays.removeItem(display);
                        mDrawingState.displays.removeItemsAt(i);
                        dc--; i--;
                        continue;
                    }

                    const sp<DisplayDevice> disp(getDisplayDevice(display));
                    if (disp != NULL) {
                        if (state.layerStack != draw[i].layerStack) {
                            disp->setLayerStack(state.layerStack);
                        }
                        if ((state.orientation != draw[i].orientation)
                                || (state.viewport != draw[i].viewport)
                                || (state.frame != draw[i].frame))
                        {
                            disp->setProjection(state.orientation,
                                    state.viewport, state.frame);
                        }
                        if (state.width != draw[i].width || state.height != draw[i].height) {
                            disp->setDisplaySize(state.width, state.height);
                        }
                    }
                }
            }

            //增加的显示设备
            for (size_t i=0 ; i<cc ; i++) {
                if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                    const DisplayDeviceState& state(curr[i]);

                    sp<DisplaySurface> dispSurface;
                    sp<IGraphicBufferProducer> producer;
                    sp<IGraphicBufferProducer> bqProducer;
                    sp<IGraphicBufferConsumer> bqConsumer;
                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
                            new GraphicBufferAlloc());

                    int32_t hwcDisplayId = -1;
                    if (state.isVirtualDisplay()) {
                        if (state.surface != NULL) {

                            int width = 0;
                            int status = state.surface->query(
                                    NATIVE_WINDOW_WIDTH, &width);
                            int height = 0;
                            status = state.surface->query(
                                    NATIVE_WINDOW_HEIGHT, &height);
                            if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
                                    (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
                                     height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
                                hwcDisplayId = allocateHwcDisplayId(state.type);
                            }

                            sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
                                    *mHwc, hwcDisplayId, state.surface,
                                    bqProducer, bqConsumer, state.displayName);

                            dispSurface = vds;
                            producer = vds;
                        }
                    } else {
                        hwcDisplayId = allocateHwcDisplayId(state.type);
                        dispSurface = new FramebufferSurface(*mHwc, state.type,
                                bqConsumer);
                        producer = bqProducer;
                    }

                    const wp<IBinder>& display(curr.keyAt(i));
                    if (dispSurface != NULL) {
                        sp<DisplayDevice> hw = new DisplayDevice(this,
                                state.type, hwcDisplayId,
                                mHwc->getFormat(hwcDisplayId), state.isSecure,
                                display, dispSurface, producer,
                                mRenderEngine->getEGLConfig());
                        hw->setLayerStack(state.layerStack);
                        hw->setProjection(state.orientation,
                                state.viewport, state.frame);
                        hw->setDisplayName(state.displayName);
                        mDisplays.add(display, hw);
                        if (state.isVirtualDisplay()) {
                            if (hwcDisplayId >= 0) {
                                mHwc->setVirtualDisplayProperties(hwcDisplayId,
                                        hw->getWidth(), hw->getHeight(),
                                        hw->getFormat());
                            }
                        } else {
                            mEventThread->onHotplugReceived(state.type, true);
                        }
                    }
                }
            }
        }
    }

    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
        sp<const DisplayDevice> disp;
        uint32_t currentlayerStack = 0;
        for (size_t i=0; i<count; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t layerStack = layer->getDrawingState().layerStack;
            if (i==0 || currentlayerStack != layerStack) {
                currentlayerStack = layerStack;
                disp.clear();
                for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                    sp<const DisplayDevice> hw(mDisplays[dpy]);
                    if (hw->getLayerStack() == currentlayerStack) {
                        if (disp == NULL) {
                            disp = hw;
                        } else {
                            disp = NULL;
                            break;
                        }
                    }
                }
            }
            if (disp == NULL) {
                disp = getDefaultDisplayDevice();
            }
            layer->updateTransformHint(disp);
        }
    }

    const LayerVector& layers(mDrawingState.layersSortedByZ);
    // layers增加
    if (currentLayers.size() > layers.size()) {
        // layers have been added
        mVisibleRegionsDirty = true;
    }

    // layers移除
    if (mLayersRemoved) {
        mLayersRemoved = false;
        mVisibleRegionsDirty = true;
        const size_t count = layers.size();
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(layers[i]);
            if (currentLayers.indexOf(layer) < 0) {
                const Layer::State& s(layer->getDrawingState());
                Region visibleReg = s.transform.transform(
                        Region(Rect(s.active.w, s.active.h)));
                invalidateLayerStack(s.layerStack, visibleReg);
            }
        }
    }
    
    commitTransaction(); //【见小节2.4.4】
    updateCursorAsync(); //【见小节2.4.5】
}

handleTransactionLocked方法的主要工作:

  1. 遍历所有Layer来执行其doTransaction方法;
  2. 处理显示设备的改变;
  3. 处理layers的改变;
  4. 提交transaction,并更新光标情况。

2.4.3 doTransaction

[-> Layer.cpp]

uint32_t Layer::doTransaction(uint32_t flags) {
    const Layer::State& s(getDrawingState()); //上次绘制状态
    const Layer::State& c(getCurrentState()); //当前设置的绘制状态

    const bool sizeChanged = (c.requested.w != s.requested.w) ||
                             (c.requested.h != s.requested.h);

    if (sizeChanged) {
        //当Layer尺寸改变,则调整surface缓存区大小
        mSurfaceFlingerConsumer->setDefaultBufferSize(
                c.requested.w, c.requested.h);
    }

    if (!isFixedSize()) {
        const bool resizePending = (c.requested.w != c.active.w) ||
                                   (c.requested.h != c.active.h);
        //当Layer不是固定大小,且请求大小和实际大小不同。
        if (resizePending && mSidebandStream == NULL) {
            flags |= eDontUpdateGeometryState;
        }
    }

    if (flags & eDontUpdateGeometryState)  {
    } else {
        Layer::State& editCurrentState(getCurrentState());
        editCurrentState.active = c.requested;
    }

    if (s.active != c.active) {
        flags |= Layer::eVisibleRegion; // invalidate且重新计算可见区域
    }

    if (c.sequence != s.sequence) {
        flags |= eVisibleRegion; // invalidate且重新计算可见区域
        this->contentDirty = true;
        const uint8_t type = c.transform.getType();
        mNeedsFiltering = (!c.transform.preserveRects() ||
                (type >= Transform::SCALE));
    }

    commitTransaction(); //【见小节2.4.4】
    return flags;
}

2.4.4 commitTransaction

void SurfaceFlinger::commitTransaction()
{
    if (!mLayersPendingRemoval.isEmpty()) {
        // Notify removed layers now that they can't be drawn from
        for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
            mLayersPendingRemoval[i]->onRemoved();
        }
        mLayersPendingRemoval.clear();
    }

    mAnimCompositionPending = mAnimTransactionPending;
    mDrawingState = mCurrentState; //设置状态
    mTransactionPending = false;
    mAnimTransactionPending = false;
    mTransactionCV.broadcast(); //唤醒
}

2.4.5 updateCursorAsync

void SurfaceFlinger::updateCursorAsync()
{
    HWComposer& hwc(getHwComposer());
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        sp<const DisplayDevice> hw(mDisplays[dpy]);
        const int32_t id = hw->getHwcDisplayId();
        if (id < 0) {
            continue;
        }
        const Vector< sp<Layer> >& currentLayers(
            hw->getVisibleLayersSortedByZ());
        const size_t count = currentLayers.size();
        HWComposer::LayerListIterator cur = hwc.begin(id);
        const HWComposer::LayerListIterator end = hwc.end(id);
        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
            if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
                continue;
            }
            const sp<Layer>& layer(currentLayers[i]);
            Rect cursorPos = layer->getPosition(hw);
            hwc.setCursorPositionAsync(id, cursorPos);
            break;
        }
    }
}

2.5 SF.handleMessageInvalidate

bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    return handlePageFlip(); //【见小节2.5.1】
}

2.5.1 SF.handlePageFlip

bool SurfaceFlinger::handlePageFlip()
{
    Region dirtyRegion;

    bool visibleRegions = false;
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    bool frameQueued = false;

    Vector<Layer*> layersWithQueuedFrames;
    for (size_t i = 0, count = layers.size(); i<count ; i++) {
        const sp<Layer>& layer(layers[i]);
        //判断Layer是否有需要更新的图层
        if (layer->hasQueuedFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(mPrimaryDispSync)) {
                //将需要更新的图层放入layersWithQueuedFrames
                layersWithQueuedFrames.push_back(layer.get());
            } else {
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    }
    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
        Layer* layer = layersWithQueuedFrames[i];
        //调用latchBuffer来处理
        const Region dirty(layer->latchBuffer(visibleRegions));
        layer->useSurfaceDamage();
        const Layer::State& s(layer->getDrawingState());
        invalidateLayerStack(s.layerStack, dirty);
    }

    mVisibleRegionsDirty |= visibleRegions;

    if (frameQueued && layersWithQueuedFrames.empty()) {
        signalLayerUpdate();
    }
    return !layersWithQueuedFrames.empty();
}

2.6 signalRefresh

void SurfaceFlinger::signalRefresh() {
    mEventQueue.refresh();
}

处理过程类似于[小节2.3] signalLayerUpdate,最终会调用[小节1.1] SF.handleMessageRefresh()。

三. rebuildLayerStacks

void SurfaceFlinger::rebuildLayerStacks() {
    if (CC_UNLIKELY(mVisibleRegionsDirty)) {
        mVisibleRegionsDirty = false;
        invalidateHwcGeometry();
        //每个显示屏中的所有可见图层列表
        const LayerVector& layers(mDrawingState.layersSortedByZ);
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            Region opaqueRegion;
            Region dirtyRegion;
            Vector< sp<Layer> > layersSortedByZ;
            const sp<DisplayDevice>& hw(mDisplays[dpy]);
            const Transform& tr(hw->getTransform());
            const Rect bounds(hw->getBounds());
            if (hw->isDisplayOn()) {
                //计算每个Layer的可见区域
                SurfaceFlinger::computeVisibleRegions(layers,
                        hw->getLayerStack(), dirtyRegion, opaqueRegion);

                const size_t count = layers.size();
                for (size_t i=0 ; i<count ; i++) {
                    const sp<Layer>& layer(layers[i]);
                    const Layer::State& s(layer->getDrawingState());
                    //当前layer和显示设备的layerStack相同
                    if (s.layerStack == hw->getLayerStack()) {
                        Region drawRegion(tr.transform(
                                layer->visibleNonTransparentRegion));
                        drawRegion.andSelf(bounds);
                        if (!drawRegion.isEmpty()) {
                            layersSortedByZ.add(layer);
                        }
                    }
                }
            }
            hw->setVisibleLayersSortedByZ(layersSortedByZ);
            hw->undefinedRegion.set(bounds);
            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
            hw->dirtyRegion.orSelf(dirtyRegion);
        }
    }
}

重建所有显示屏的各个可见Layer列表,根据Z轴排序。

四. setUpHWComposer

void SurfaceFlinger::setUpHWComposer() {
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
        bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
        bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
        bool mustRecompose = dirty && !(empty && wasEmpty);
        mDisplays[dpy]->beginFrame(mustRecompose);

        if (mustRecompose) {
            mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
        }
    }

    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        if (CC_UNLIKELY(mHwWorkListDirty)) {
            mHwWorkListDirty = false;
            for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                sp<const DisplayDevice> hw(mDisplays[dpy]);
                const int32_t id = hw->getHwcDisplayId();
                if (id >= 0) {
                    const Vector< sp<Layer> >& currentLayers(
                        hw->getVisibleLayersSortedByZ());
                    const size_t count = currentLayers.size();
                    //在HWComposer中创建列表
                    if (hwc.createWorkList(id, count) == NO_ERROR) {
                        HWComposer::LayerListIterator cur = hwc.begin(id);
                        const HWComposer::LayerListIterator end = hwc.end(id);
                        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
                            const sp<Layer>& layer(currentLayers[i]);
                            layer->setGeometry(hw, *cur);
                        }
                    }
                }
            }
        }

        //设置每帧的数据
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            sp<const DisplayDevice> hw(mDisplays[dpy]);
            const int32_t id = hw->getHwcDisplayId();
            if (id >= 0) {
                const Vector< sp<Layer> >& currentLayers(
                    hw->getVisibleLayersSortedByZ());
                const size_t count = currentLayers.size();
                HWComposer::LayerListIterator cur = hwc.begin(id);
                const HWComposer::LayerListIterator end = hwc.end(id);
                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
                    /*
                     * update the per-frame h/w composer data for each layer
                     * and build the transparent region of the FB
                    /为每一个layer,更新每帧h/w合成器的数据
                    const sp<Layer>& layer(currentLayers[i]);
                    layer->setPerFrameData(hw, *cur);
                }
            }
        }

        //在每一个显示屏上,尝试使用cursor overlay
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            sp<const DisplayDevice> hw(mDisplays[dpy]);
            const int32_t id = hw->getHwcDisplayId();
            if (id >= 0) {
                const Vector< sp<Layer> >& currentLayers(
                    hw->getVisibleLayersSortedByZ());
                const size_t count = currentLayers.size();
                HWComposer::LayerListIterator cur = hwc.begin(id);
                const HWComposer::LayerListIterator end = hwc.end(id);
                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
                    const sp<Layer>& layer(currentLayers[i]);
                    if (layer->isPotentialCursor()) {
                        cur->setIsCursorLayerHint();
                        break;
                    }
                }
            }
        }

        status_t err = hwc.prepare(); //【见小节4.1】
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            sp<const DisplayDevice> hw(mDisplays[dpy]);
            hw->prepareFrame(hwc);
        }
    }
}

4.1 HWC.prepare

status_t HWComposer::prepare() {
    Mutex::Autolock _l(mDisplayLock);
    for (size_t i=0 ; i<mNumDisplays ; i++) {
        DisplayData& disp(mDisplayData[i]);
        if (disp.framebufferTarget) {
            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
        }
        mLists[i] = disp.list;
        if (mLists[i]) {
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
                mLists[i]->outbuf = disp.outbufHandle;
                mLists[i]->outbufAcquireFenceFd = -1;
            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
            } else {
                mLists[i]->dpy = EGL_NO_DISPLAY;
                mLists[i]->sur = EGL_NO_SURFACE;
            }
        }
    }

    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);

    if (err == NO_ERROR) {
        for (size_t i=0 ; i<mNumDisplays ; i++) {
            DisplayData& disp(mDisplayData[i]);
            disp.hasFbComp = false;
            disp.hasOvComp = false;
            if (disp.list) {
                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
                    hwc_layer_1_t& l = disp.list->hwLayers[i];

                    if (l.flags & HWC_SKIP_LAYER) {
                        l.compositionType = HWC_FRAMEBUFFER;
                    }
                    if (l.compositionType == HWC_FRAMEBUFFER) {
                        disp.hasFbComp = true;
                    }
                    if (l.compositionType == HWC_OVERLAY) {
                        disp.hasOvComp = true;
                    }
                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
                        disp.hasOvComp = true;
                    }
                }
                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
                    disp.hasFbComp = true;
                }
            } else {
                disp.hasFbComp = true;
            }
        }
    }
    return (status_t)err;
}  

五. doComposition

void SurfaceFlinger::doComposition() {
    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        const sp<DisplayDevice>& hw(mDisplays[dpy]);
        if (hw->isDisplayOn()) {
            //将脏区域转换为此屏幕的坐标空间
            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));

            //如果需要,则重绘framebuffer【见小节5.1】
            doDisplayComposition(hw, dirtyRegion);

            hw->dirtyRegion.clear();
            hw->flip(hw->swapRegion);
            hw->swapRegion.clear();
        }
        //通知h/w我们已完成合成操作
        hw->compositionComplete();
    }
    postFramebuffer(); //【见小节5.3】
}

5.1 doDisplayComposition

void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
        const Region& inDirtyRegion)
{
    bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
    if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
        return;
    }
    Region dirtyRegion(inDirtyRegion);

    //计算需要更新的区域
    hw->swapRegion.orSelf(dirtyRegion);

    uint32_t flags = hw->getFlags();
    if (flags & DisplayDevice::SWAP_RECTANGLE) {
        //矩形更新模式
        dirtyRegion.set(hw->swapRegion.bounds());
    } else {
        if (flags & DisplayDevice::PARTIAL_UPDATES) {
            //部分更新模式
            dirtyRegion.set(hw->swapRegion.bounds());
        } else {
            //更新区域为整个屏幕
            dirtyRegion.set(hw->bounds());
            hw->swapRegion = dirtyRegion;
        }
    }

    if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
        if (!doComposeSurfaces(hw, dirtyRegion)) return;
    } else {
        RenderEngine& engine(getRenderEngine());
        mat4 colorMatrix = mColorMatrix;
        if (mDaltonize) {
            colorMatrix = colorMatrix * mDaltonizer();
        }
        mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
        doComposeSurfaces(hw, dirtyRegion);
        engine.setupColorTransform(oldMatrix);
    }

    //更新交换区域,并清除脏区域
    hw->swapRegion.orSelf(dirtyRegion);
    //交换buffer,输出图像
    hw->swapBuffers(getHwComposer());
}

5.2 doComposeSurfaces

bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
    RenderEngine& engine(getRenderEngine());
    const int32_t id = hw->getHwcDisplayId();
    HWComposer& hwc(getHwComposer());
    HWComposer::LayerListIterator cur = hwc.begin(id);
    const HWComposer::LayerListIterator end = hwc.end(id);

    bool hasGlesComposition = hwc.hasGlesComposition(id);
    if (hasGlesComposition) {
        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
            eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
            }
            return false;
        }

        const bool hasHwcComposition = hwc.hasHwcComposition(id);
        if (hasHwcComposition) {
            engine.clearWithColor(0, 0, 0, 0);
        } else {
            //全屏
            const Region bounds(hw->getBounds());
            const Region letterbox(bounds.subtract(hw->getScissor()));
            Region region(hw->undefinedRegion.merge(letterbox));
            region.andSelf(dirty);

            if (!region.isEmpty()) {
                //能发生在SurfaceView
                drawWormhole(hw, region);
            }
        }

        if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
            const Rect& bounds(hw->getBounds());
            const Rect& scissor(hw->getScissor());
            if (scissor != bounds) {
                const uint32_t height = hw->getHeight();
                engine.setScissor(scissor.left, height - scissor.bottom,
                        scissor.getWidth(), scissor.getHeight());
            }
        }
    }

    const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
    const size_t count = layers.size();
    const Transform& tr = hw->getTransform();
    if (cur != end) {
        //使用h/w composer
        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
            const sp<Layer>& layer(layers[i]);
            const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
            if (!clip.isEmpty()) {
                switch (cur->getCompositionType()) {
                    case HWC_CURSOR_OVERLAY:
                    case HWC_OVERLAY: {
                        const Layer::State& state(layer->getDrawingState());
                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)
                                && i
                                && layer->isOpaque(state) && (state.alpha == 0xFF)
                                && hasGlesComposition) {
                            layer->clearWithOpenGL(hw, clip);
                        }
                        break;
                    }
                    case HWC_FRAMEBUFFER: {
                        layer->draw(hw, clip); //执行图像绘制
                        break;
                    }
                    case HWC_FRAMEBUFFER_TARGET: {
                        break;
                    }
                }
            }
            layer->setAcquireFence(hw, *cur);
        }
    } else {
        //不使用h/w composer
        for (size_t i=0 ; i<count ; ++i) {
            const sp<Layer>& layer(layers[i]);
            const Region clip(dirty.intersect(
                    tr.transform(layer->visibleRegion)));
            if (!clip.isEmpty()) {
                layer->draw(hw, clip);
            }
        }
    }

    engine.disableScissor();
    return true;
}

5.3 postFramebuffer

void SurfaceFlinger::postFramebuffer()
{
    const nsecs_t now = systemTime();
    mDebugInSwapBuffers = now;

    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        if (!hwc.supportsFramebufferTarget()) {
            getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
        }
        hwc.commit(); //【见小节5.4】
    }

    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        sp<const DisplayDevice> hw(mDisplays[dpy]);
        const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
        hw->onSwapBuffersCompleted(hwc);
        const size_t count = currentLayers.size();
        int32_t id = hw->getHwcDisplayId();
        if (id >=0 && hwc.initCheck() == NO_ERROR) {
            HWComposer::LayerListIterator cur = hwc.begin(id);
            const HWComposer::LayerListIterator end = hwc.end(id);
            for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
                currentLayers[i]->onLayerDisplayed(hw, &*cur);
            }
        } else {
            for (size_t i = 0; i < count; i++) {
                currentLayers[i]->onLayerDisplayed(hw, NULL);
            }
        }
    }

    mLastSwapBufferTime = systemTime() - now;
    mDebugInSwapBuffers = 0;

    uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
    if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
        logFrameStats();
    }
}

将数据写入framebuffer则完成物理屏幕的图像显示。

5.4 HWC.commit

status_t HWComposer::commit() {
    int err = NO_ERROR;
    if (mHwc) {
        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
            mLists[0]->dpy = eglGetCurrentDisplay();
            mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
        }

        for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
            DisplayData& disp(mDisplayData[i]);
            if (disp.outbufHandle) {
                mLists[i]->outbuf = disp.outbufHandle;
                mLists[i]->outbufAcquireFenceFd =
                        disp.outbufAcquireFence->dup();
            }
        }
        //处理图像输出到FrameBuffer
        err = mHwc->set(mHwc, mNumDisplays, mLists);

        for (size_t i=0 ; i<mNumDisplays ; i++) {
            DisplayData& disp(mDisplayData[i]);
            disp.lastDisplayFence = disp.lastRetireFence;
            disp.lastRetireFence = Fence::NO_FENCE;
            if (disp.list) {
                if (disp.list->retireFenceFd != -1) {
                    disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
                    disp.list->retireFenceFd = -1;
                }
                disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
            }
        }
    }
    return (status_t)err;
}

六. postComposition

void SurfaceFlinger::postComposition()
{
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    const size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
        layers[i]->onPostComposition();
    }

    const HWComposer& hwc = getHwComposer();
    sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);

    if (presentFence->isValid()) {
        if (mPrimaryDispSync.addPresentFence(presentFence)) {
            enableHardwareVsync();
        } else {
            disableHardwareVsync(false);
        }
    }

    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
    if (kIgnorePresentFences) {
        if (hw->isDisplayOn()) {
            enableHardwareVsync();
        }
    }

    if (mAnimCompositionPending) {
        mAnimCompositionPending = false;

        if (presentFence->isValid()) {
            mAnimFrameTracker.setActualPresentFence(presentFence);
        } else {
            nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
            mAnimFrameTracker.setActualPresentTime(presentTime);
        }
        mAnimFrameTracker.advanceFrame();
    }

    if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
        return;
    }

    nsecs_t currentTime = systemTime();
    if (mHasPoweredOff) {
        mHasPoweredOff = false;
    } else {
        nsecs_t period = mPrimaryDispSync.getPeriod();
        nsecs_t elapsedTime = currentTime - mLastSwapTime;
        size_t numPeriods = static_cast<size_t>(elapsedTime / period);
        if (numPeriods < NUM_BUCKETS - 1) {
            mFrameBuckets[numPeriods] += elapsedTime;
        } else {
            mFrameBuckets[NUM_BUCKETS - 1] += elapsedTime;
        }
        mTotalTime += elapsedTime;
    }
    mLastSwapTime = currentTime;
}

七. 小结

简单总结图像输出流程:

  1. preComposition:根据上次绘制的图层中是否有更新,来决定是否执行invalidate过程;
  2. rebuildLayerStacks: 重建每个显示屏的所有可见Layer列表;
  3. setUpHWComposer:更新HWComposer的图层
  4. doComposition:合成所有图层的图像
  5. postComposition:回调每个layer的onPostComposition。

Choreographer原理

$
0
0
Choreographer.java
DisplayEventReceiver.java
frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
frameworks/native/libs/gui/DisplayEventReceiver.cpp

一. 概述

前面两篇文章介绍了SurfaceFlinger原理,讲述了SurfaceFlinger的启动过程,绘制过程,以及Vsync处理过程。 本文再介绍一下Choreographer的启动与Vsync处理过程。

二. Choreographer启动流程

在Activity启动过程,执行完onResume后,会调用Activity.makeVisible(),然后再调用到addView(), 层层调用会进入如下方法:

public ViewRootImpl(Context context, Display display) {
    ...
    //这里便出现获取Choreographer实例【见小节2.1】
    mChoreographer = Choreographer.getInstance();
    ...
}

2.1 getInstance

[-> Choreographer.java]

public static Choreographer getInstance() {
    return sThreadInstance.get(); //单例模式
}

private static final ThreadLocal<Choreographer> sThreadInstance =
    new ThreadLocal<Choreographer>() {

    protected Choreographer initialValue() {
        Looper looper = Looper.myLooper(); //获取当前线程的Looper
        if (looper == null) {
            throw new IllegalStateException("The current thread must have a looper!");
        }
        return new Choreographer(looper); //【见小节2.2】
    }
};

当前所在线程为UI线程,也就是常说的主线程。

2.2 创建Choreographer

[-> Choreographer.java]

private Choreographer(Looper looper) {
    mLooper = looper;
    //创建Handler对象【见小节2.3】
    mHandler = new FrameHandler(looper);
    //创建用于接收VSync信号的对象【见小节2.4】
    mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
    mLastFrameTimeNanos = Long.MIN_VALUE;
    mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
    //创建回调对象
    mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
    for (int i = 0; i <= CALLBACK_LAST; i++) {
        mCallbackQueues[i] = new CallbackQueue();
    }
}
  • mLastFrameTimeNanos:是指上一次帧绘制时间点;
  • mFrameIntervalNanos:帧间时长,一般等于16.7ms.

2.3 FrameHandler

[-> Choreographer.java ::FrameHandler]

private final class FrameHandler extends Handler {
    public FrameHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_DO_FRAME:
                doFrame(System.nanoTime(), 0);
                break;
            case MSG_DO_SCHEDULE_VSYNC:
                doScheduleVsync();
                break;
            case MSG_DO_SCHEDULE_CALLBACK:
                doScheduleCallback(msg.arg1);
                break;
        }
    }
}

2.4 创建FrameDisplayEventReceiver

[-> Choreographer.java ::FrameDisplayEventReceiver]

private final class FrameDisplayEventReceiver extends DisplayEventReceiver
        implements Runnable {

    public FrameDisplayEventReceiver(Looper looper) {
        super(looper); //【见小节2.4.1】
    }
}

2.4.1 DisplayEventReceiver

[-> DisplayEventReceiver.java]

public DisplayEventReceiver(Looper looper) {
    mMessageQueue = looper.getQueue(); //获取主线程的消息队列
    //【见小节2.4.2】
    mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue);
}

经过JNI调用进入如下Native方法。

2.4.2 nativeInit

[-> android_view_DisplayEventReceiver.cpp]

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    ...
    //【见小节2.4.3】
    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
            receiverWeak, messageQueue);
    //【见小节2.4.4】
    status_t status = receiver->initialize();
    ...

    //获取DisplayEventReceiver对象的引用
    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); 
    return reinterpret_cast<jlong>(receiver.get());
}

2.4.3 创建NativeDisplayEventReceiver

[-> android_view_DisplayEventReceiver.cpp]

NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
        jobject receiverWeak, const sp<MessageQueue>& messageQueue) :
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mMessageQueue(messageQueue), mWaitingForVsync(false) {
    ALOGV("receiver %p ~ Initializing display event receiver.", this);
}

NativeDisplayEventReceiver继承于LooperCallback对象,此处mReceiverWeakGlobal记录的是Java层 DisplayEventReceiver对象的全局引用。

2.4.4 initialize

[-> android_view_DisplayEventReceiver.cpp]

status_t NativeDisplayEventReceiver::initialize() {
    //mReceiver为DisplayEventReceiver类型
    status_t result = mReceiver.initCheck();
    ...
    //监听mReceiver的所获取的文件句柄。
    int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    ...
    
    return OK;
}

此处跟文章SurfaceFlinger原理(一)的【小节2.8】的监听原理一样。 监听mReceiver的所获取的文件句柄,一旦有数据到来,则回调this(此处NativeDisplayEventReceiver)中所复写LooperCallback对象的 handleEvent。

2.5 handleEvent

[-> android_view_DisplayEventReceiver.cpp]

int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    ...
    nsecs_t vsyncTimestamp;
    int32_t vsyncDisplayId;
    uint32_t vsyncCount;
    //清除所有的pending事件,只保留最后一次vsync【见小节2.5.1】
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
        mWaitingForVsync = false;
        //分发Vsync【见小节2.5.2】
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
    }
    return 1;
}

2.5.1 processPendingEvents

bool NativeDisplayEventReceiver::processPendingEvents(
        nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) {
    bool gotVsync = false;
    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
    ssize_t n;
    while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
        for (ssize_t i = 0; i < n; i++) {
            const DisplayEventReceiver::Event& ev = buf[i];
            switch (ev.header.type) {
            case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                gotVsync = true; //获取VSync信号
                *outTimestamp = ev.header.timestamp;
                *outId = ev.header.id;
                *outCount = ev.vsync.count;
                break;
            case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
                break;
            default:
                break;
            }
        }
    }
    return gotVsync;
}

遍历所有的事件,当有多个VSync事件到来,则只关注最近一次的事件。

2.5.2 dispatchVsync

void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();

    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        //【见小节2.6】
        env->CallVoidMethod(receiverObj.get(),
                gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
    }

    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}

此处调用到Java层的DisplayEventReceiver对象的dispatchVsync()方法,接下来进入Java层。

2.6 dispatchVsync

[-> DisplayEventReceiver.java]

private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
    //【见小节2.7】
    onVsync(timestampNanos, builtInDisplayId, frame);
}

再回到【小节2.2】,可知Choreographer对象实例化的过程,创建的对象是DisplayEventReceiver子类 FrameDisplayEventReceiver对象,接下来进入该对象。

2.7 onVsync

[-> Choreographer.java ::FrameDisplayEventReceiver]

private final class FrameDisplayEventReceiver extends DisplayEventReceiver
        implements Runnable {
    private boolean mHavePendingVsync;
    private long mTimestampNanos;
    private int mFrame;

    @Override
    public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
        //忽略来自第二显示屏的Vsync
        if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
            scheduleVsync();
            return;
        }
        ...
        
        mTimestampNanos = timestampNanos;
        mFrame = frame;
        //该消息的callback为当前对象FrameDisplayEventReceiver
        Message msg = Message.obtain(mHandler, this);
        msg.setAsynchronous(true);
        //此处mHandler为FrameHandler
        mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
    }

    @Override
    public void run() {
        mHavePendingVsync = false;
        doFrame(mTimestampNanos, mFrame); //【见小节2.8】
    }
}

可见onVsync()过程是通过FrameHandler向主线程Looper发送了一个自带callback的消息 callback为FrameDisplayEventReceiver。 当主线程Looper执行到该消息时,则调用FrameDisplayEventReceiver.run()方法,紧接着便是调用doFrame,如下:

2.8 doFrame

[-> Choreographer.java]

void doFrame(long frameTimeNanos, int frame) {
    final long startNanos;
    synchronized (mLock) {
        if (!mFrameScheduled) {
            return; // mFrameScheduled=false,则直接返回。
        }

        long intendedFrameTimeNanos = frameTimeNanos; //原本计划的绘帧时间点
        startNanos = System.nanoTime();
        final long jitterNanos = startNanos - frameTimeNanos;
        if (jitterNanos >= mFrameIntervalNanos) {
            
            final long skippedFrames = jitterNanos / mFrameIntervalNanos;
            //当掉帧个数超过30,则输出相应log
            if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                        + "The application may be doing too much work on its main thread.");
            }
            final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
            frameTimeNanos = startNanos - lastFrameOffset; //对齐帧的时间间隔
        }

        if (frameTimeNanos < mLastFrameTimeNanos) {
            scheduleVsyncLocked();
            return;
        }

        mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
        mFrameScheduled = false;
        mLastFrameTimeNanos = frameTimeNanos;
    }

    try {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");

        mFrameInfo.markInputHandlingStart();
        doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);

        mFrameInfo.markAnimationsStart();
        doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);

        mFrameInfo.markPerformTraversalsStart();
        doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);

        doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
    }
}
  1. 每调用一次scheduleFrameLocked(),则mFrameScheduled为true,能执行一次 doFrame()操作。
  2. 最终有4个回调方法,依次为如下:
    • INPUT:输入事件
    • ANIMATION:动画
    • TRAVERSAL:窗口刷新
    • COMMIT

2.8.1 doCallbacks

[-> Choreographer.java]

void doCallbacks(int callbackType, long frameTimeNanos) {
    CallbackRecord callbacks;
    synchronized (mLock) {
        final long now = System.nanoTime();
        // 从队列查找相应类型的CallbackRecord对象【见小节2.8.2】
        callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
                now / TimeUtils.NANOS_PER_MS);
        if (callbacks == null) {
            return;  //当队列为空,则直接返回
        }
        mCallbacksRunning = true;

        if (callbackType == Choreographer.CALLBACK_COMMIT) {
            final long jitterNanos = now - frameTimeNanos;
            //当commit类型回调执行的时间点超过2帧,则更新mLastFrameTimeNanos。
            if (jitterNanos >= 2 * mFrameIntervalNanos) {
                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
                        + mFrameIntervalNanos;
                frameTimeNanos = now - lastFrameOffset;
                mLastFrameTimeNanos = frameTimeNanos;
            }
        }
    }
    try {
        for (CallbackRecord c = callbacks; c != null; c = c.next) {
            c.run(frameTimeNanos); //【见小节2.9】
        }
    } finally {
        ... //回收callbacks,加入mCallbackPool对象池
    }
}

2.8.2 extractDueCallbacksLocked

[-> Choreographer.java ::CallbackQueue]

private final class CallbackQueue {
    public CallbackRecord extractDueCallbacksLocked(long now) {
        CallbackRecord callbacks = mHead;
        //当队列头部的callbacks对象为空,或者执行时间还没到达,则直接返回
        if (callbacks == null || callbacks.dueTime > now) {
            return null; 
        }

        CallbackRecord last = callbacks;
        CallbackRecord next = last.next;
        while (next != null) {
            if (next.dueTime > now) {
                last.next = null;
                break;
            }
            last = next;
            next = next.next;
        }
        mHead = next;
        return callbacks;
    }
}

2.9 CallbackRecord.run

[-> Choreographer.java ::CallbackRecord]

private static final class CallbackRecord {
    public CallbackRecord next;
    public long dueTime;
    public Object action; // Runnable or FrameCallback
    public Object token;

    public void run(long frameTimeNanos) {
        if (token == FRAME_CALLBACK_TOKEN) {
            ((FrameCallback)action).doFrame(frameTimeNanos);
        } else {
            ((Runnable)action).run();
        }
    }
}

这里的回调方法run()有两种执行情况:

  • 当token的数据类型为FRAME_CALLBACK_TOKEN,则执行该对象的doFrame()方法;
  • 当token为其他类型,则执行该对象的run()方法。

在前面小节【2.8】doFrame()过程有一个判断变量mFrameScheduled,有两种执行情况:

  • 当该值为true则执行动画,执行完本次操作则再次设置该值为false;
  • 否则并不会执行动画。

对于底层Vsync信号每间隔16.7ms,上层都会接收到该信号。但对于系统会有需要,才会更新动画, 那么需要的场景便是由WMS调用scheduleAnimationLocked()方法来设置mFrameScheduled=true来触发动画, 接下来说说动画控制的过程

三. 动画显示过程

调用栈:

WMS.scheduleAnimationLocked
  postFrameCallback
    postFrameCallbackDelayed
      postCallbackDelayedInternal
        scheduleFrameLocked

3.1 WMS.scheduleAnimationLocked

[-> WindowManagerService.java]

void scheduleAnimationLocked() {
     if (!mAnimationScheduled) { 
         mAnimationScheduled = true;
         //【见小节3.2】
         mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback);
     }
 }

只有当mAnimationScheduled=false时,才会执行postFrameCallback(),其中参数为mAnimator对象的 成员变量mAnimationFrameCallback,该对象的初始化过程:

3.1.1 创建WMS

private WindowManagerService(
    ...
    mAnimator = new WindowAnimator(this); //【见小节3.1.2】
    ...
}

3.1.2 创建WindowAnimator

[-> WindowAnimator.java]

WindowAnimator(final WindowManagerService service) {
    mService = service;
    mContext = service.mContext;
    mPolicy = service.mPolicy;

    mAnimationFrameCallback = new Choreographer.FrameCallback() {
        public void doFrame(long frameTimeNs) {
            synchronized (mService.mWindowMap) {
                mService.mAnimationScheduled = false;
                animateLocked(frameTimeNs);
            }
        }
    };
}

mAnimationFrameCallback的数据类型为Choreographer.FrameCallback。

3.2 postFrameCallback

[-> Choreographer.java]

public void postFrameCallback(FrameCallback callback) {
    postFrameCallbackDelayed(callback, 0);
}

public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
    ...
    //【见小节3.3】
    postCallbackDelayedInternal(CALLBACK_ANIMATION,
            callback, FRAME_CALLBACK_TOKEN, delayMillis);
}

3.3 postCallbackDelayedInternal

[-> Choreographer.java]

// callbackType为动画,action为mAnimationFrameCallback
// token为FRAME_CALLBACK_TOKEN,delayMillis=0
private void postCallbackDelayedInternal(int callbackType,
    Object action, Object token, long delayMillis) {

    synchronized (mLock) {
        final long now = SystemClock.uptimeMillis();
        final long dueTime = now + delayMillis;
        //添加到mCallbackQueues队列
        mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);

        if (dueTime <= now) {
            scheduleFrameLocked(now);
        } else {
            //发送消息MSG_DO_SCHEDULE_CALLBACK
            Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
            msg.arg1 = callbackType;
            msg.setAsynchronous(true);
            mHandler.sendMessageAtTime(msg, dueTime);
        }
    }
}

发送MSG_DO_SCHEDULE_CALLBACK消息后,主线程接收后进入FrameHandler的handleMessage()操作,如下方法。

3.4 MSG_DO_SCHEDULE_CALLBACK

[-> Choreographer.java ::FrameHandler]

private final class FrameHandler extends Handler {

    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_DO_FRAME:
                doFrame(System.nanoTime(), 0);
                break;
            case MSG_DO_SCHEDULE_VSYNC:
                doScheduleVsync();
                break;
            case MSG_DO_SCHEDULE_CALLBACK:
                doScheduleCallback(msg.arg1); //【见小节3.5】
                break;
        }
    }
}

3.5 doScheduleCallback

[-> Choreographer.java]

void doScheduleCallback(int callbackType) {
    synchronized (mLock) {
        if (!mFrameScheduled) {
            final long now = SystemClock.uptimeMillis();
            if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
                scheduleFrameLocked(now); //【见小节3.6】
            }
        }
    }
}

3.6 scheduleFrameLocked

[-> Choreographer.java]

private void scheduleFrameLocked(long now) {
    if (!mFrameScheduled) {
        mFrameScheduled = true;
        if (USE_VSYNC) {
            if (isRunningOnLooperThreadLocked()) {
                //当运行在Looper线程,则立刻调度vsync
                scheduleVsyncLocked(); 
            } else {
                //否则,发送消息到UI线程
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtFrontOfQueue(msg);
            }
        } else {
            final long nextFrameTime = Math.max(
                    mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
            Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
            msg.setAsynchronous(true);
            mHandler.sendMessageAtTime(msg, nextFrameTime);
        }
    }
}

该方法的功能:

  1. 当运行在Looper线程,则立刻调度scheduleVsyncLocked();
  2. 当运行在其他线程,则通过发送一个消息到Looper线程,然后再执行scheduleVsyncLocked();

3.7 scheduleVsyncLocked

[-> Choreographer.java]

private void scheduleVsyncLocked() {
    mDisplayEventReceiver.scheduleVsync(); //【见小节3.8】
}

mDisplayEventReceiver对象是在【小节2.2】Choreographer的实例化过程所创建的。

3.8 scheduleVsync

[-> DisplayEventReceiver.java]

public void scheduleVsync() {
     if (mReceiverPtr == 0) {
        ...
     } else {
         nativeScheduleVsync(mReceiverPtr);
     }
}

3.9 nativeScheduleVsync

[-> android_view_DisplayEventReceiver.cpp]

static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    sp<NativeDisplayEventReceiver> receiver =
            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    status_t status = receiver->scheduleVsync();
    ...
}

3.10 scheduleVsync

[-> android_view_DisplayEventReceiver.cpp]

status_t NativeDisplayEventReceiver::scheduleVsync() {
    if (!mWaitingForVsync) {
        nsecs_t vsyncTimestamp;
        int32_t vsyncDisplayId;
        uint32_t vsyncCount;
        processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
        //【见小节3.11】
        status_t status = mReceiver.requestNextVsync();
        ...

        mWaitingForVsync = true;
    }
    return OK;
}

3.11 requestNextVsync

[-> DisplayEventReceiver.cpp]

status_t DisplayEventReceiver::requestNextVsync() {
    if (mEventConnection != NULL) {
        mEventConnection->requestNextVsync();
        return NO_ERROR;
    }
    return NO_INIT;
}

这里就先不继续往下写了,该方法的作用请求下一次Vsync信息处理。 当Vsync信号到来,由于mFrameScheduled=true,则继续【小节2.9】CallbackRecord.run()方法。

四. 动画处理

根据[小节3.1.2]mAnimationFrameCallback.FrameCallback方法,进而调用animateLocked().

4.1 animateLocked

[-> WindowAnimator.java]

private void animateLocked(long frameTimeNs) {
    if (!mInitialized) {
        return;
    }

    mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
    mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
    boolean wasAnimating = mAnimating;
    mAnimating = false;
    mAppWindowAnimating = false;

    SurfaceControl.openTransaction(); //打开transacion
    SurfaceControl.setAnimationTransaction();
    try {
        final int numDisplays = mDisplayContentsAnimators.size();
        for (int i = 0; i < numDisplays; i++) {
            final int displayId = mDisplayContentsAnimators.keyAt(i);
            updateAppWindowsLocked(displayId);
            DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);

            final ScreenRotationAnimation screenRotationAnimation =
                    displayAnimator.mScreenRotationAnimation;
            if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
                if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
                    mAnimating = true;
                } else {
                    mBulkUpdateParams |= SET_UPDATE_ROTATION;
                    screenRotationAnimation.kill();
                    displayAnimator.mScreenRotationAnimation = null;

                    if (mService.mAccessibilityController != null
                            && displayId == Display.DEFAULT_DISPLAY) {
                        mService.mAccessibilityController.onRotationChangedLocked(
                                mService.getDefaultDisplayContentLocked(), mService.mRotation);
                    }
                }
            }

            //更新所有应用的动画,包括正在退出的应用
            updateWindowsLocked(displayId);
            updateWallpaperLocked(displayId);

            final WindowList windows = mService.getWindowListLocked(displayId);
            final int N = windows.size();
            for (int j = 0; j< N; j++) {
                //输出动画
                windows.get(j).mWinAnimator.prepareSurfaceLocked(true);
            }
        }

        for (int i = 0; i < numDisplays; i++) {
            final int displayId = mDisplayContentsAnimators.keyAt(i);

            testTokenMayBeDrawnLocked(displayId);

            final ScreenRotationAnimation screenRotationAnimation =
                    mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
            if (screenRotationAnimation != null) {
                screenRotationAnimation.updateSurfacesInTransaction();
            }

            mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();

            if (mService.mAccessibilityController != null
                    && displayId == Display.DEFAULT_DISPLAY) {
                mService.mAccessibilityController.drawMagnifiedRegionBorderIfNeededLocked();
            }
        }

        if (mAnimating) {
            mService.scheduleAnimationLocked();
        }

        mService.setFocusedStackLayer();

        if (mService.mWatermark != null) {
            mService.mWatermark.drawIfNeeded();
        }
    } catch (RuntimeException e) {
        Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
    } finally {
        SurfaceControl.closeTransaction(); //关闭transacion
    }

    boolean hasPendingLayoutChanges = false;
    final int numDisplays = mService.mDisplayContents.size();
    for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
        final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
        final int pendingChanges = getPendingLayoutChanges(displayContent.getDisplayId());
        if ((pendingChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
            mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
        }
        if (pendingChanges != 0) {
            hasPendingLayoutChanges = true;
        }
    }

    boolean doRequest = false;
    if (mBulkUpdateParams != 0) {
        doRequest = mService.copyAnimToLayoutParamsLocked();
    }

    if (hasPendingLayoutChanges || doRequest) {
        mService.requestTraversalLocked();
    }

    if (!mAnimating && wasAnimating) {
        mService.requestTraversalLocked();
    }
}

未完待续。。。

以Window视角来看startActivity

$
0
0

基于Android 6.0源码, 从Window角度来分析Activity启动过程。

一. 概述

前面的文章startActivity启动过程分析,已从AMS的角度讲述了Activity启动过程,那么本文从WMS的角度说一说这个过程。

先用上一篇文章的流程图来简单回顾一下:点击查看大图

start_activity

接下来,从文章startActivity启动过程分析的小节[2.10] AS.startActivityLocked()开始说起。

二. Window处理流程

2.1 AS.startActivityLocked

[-> ActivityStack.java]

final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition, Bundle options) {
    TaskRecord rTask = r.task;
    final int taskId = rTask.taskId;
    if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
        insertTaskAtTop(rTask, r);
        //将Window相应task移至顶部[见小节2.1.1]
        mWindowManager.moveTaskToTop(taskId); 
    }
    TaskRecord task = null;
    if (!newTask) {
      boolean startIt = true;
      for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
        task = mTaskHistory.get(taskNdx);
        if (task == r.task) {
          if (!startIt) {
              task.addActivityToTop(r);
              r.putInHistory();
              //创建AppWindowToken对象 [见小节2.1.2]
              mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                    r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                    (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0,
                    r.userId, r.info.configChanges, task.voiceSession != null,
                    r.mLaunchTaskBehind);
              return;
          }
          break;
        } 
        ...
      }
    }
    ...
    
    if (!isHomeStack() || numActivities() > 0) {
        //当切换到新的task,或者下一个activity进程目前并没有运行
        boolean showStartingIcon = newTask;
        ProcessRecord proc = r.app;
        if (proc == null) {
            proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
        }

        if (proc == null || proc.thread == null) {
            showStartingIcon = true;
        }
        if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
            mNoAnimActivities.add(r);
        } else {
            //设置transition方式[见小节2.1.3]
            mWindowManager.prepareAppTransition(newTask
                    ? r.mLaunchTaskBehind
                            ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
                            : AppTransition.TRANSIT_TASK_OPEN
                    : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
            mNoAnimActivities.remove(r);
        }
        mWindowManager.addAppToken(...);
        
        boolean doShow = true;
        if (newTask) {
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                resetTaskIfNeededLocked(r, r);
                doShow = topRunningNonDelayedActivityLocked(null) == r;
            }
        } else if (options != null && new ActivityOptions(options).getAnimationType()
                == ActivityOptions.ANIM_SCENE_TRANSITION) {
            doShow = false;
        }
        if (r.mLaunchTaskBehind) {
            mWindowManager.setAppVisibility(r.appToken, true);
            ensureActivitiesVisibleLocked(null, 0);
        } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
            ActivityRecord prev = mResumedActivity;
            mWindowManager.setAppStartingWindow(
                    r.appToken, r.packageName, r.theme,
                    mService.compatibilityInfoForPackageLocked(
                             r.info.applicationInfo), r.nonLocalizedLabel,
                    r.labelRes, r.icon, r.logo, r.windowFlags,
                    prev != null ? prev.appToken : null, showStartingIcon);
            r.mStartingWindowShown = true;
        }
    } else {
        mWindowManager.addAppToken(...);
        ...
    }

    if (doResume) {
        //该方法内部调用AS.resumeTopActivityInnerLocked [见流程2.2]
        mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
    }
}

此处涉及WMS的有以下过程:

  • WMS.moveTaskToTop:将Window相应task移至顶部;
  • WMS.addAppToken:创建AppWindowToken对象atoken,并添加到mTokenMap;
  • WMS.prepareAppTransition:设置transition方式以及5s超时消息;
  • WMS.setAppStartingWindow:创建startingData启动数据,并发送消息到”android.display”线程来处理ADD_STARTING消息。

2.1.1 WMS.moveTaskToTop

public void moveTaskToTop(int taskId) {
    final long origId = Binder.clearCallingIdentity();
    try {
        synchronized(mWindowMap) {
            Task task = mTaskIdToTask.get(taskId);
            if (task == null) {
                return;
            }
            final TaskStack stack = task.mStack;
            final DisplayContent displayContent = task.getDisplayContent();
            //将该task所属的栈 移至display的顶部
            displayContent.moveStack(stack, true);
            if (displayContent.isDefaultDisplay) {
                final TaskStack homeStack = displayContent.getHomeStack();
                if (homeStack != stack) {
                    //当非home栈移至顶部,则把home栈移至底部
                    displayContent.moveStack(homeStack, false);
                }
            }
            //将该task 移至栈的顶部
            stack.moveTaskToTop(task);
            if (mAppTransition.isTransitionSet()) {
                task.setSendingToBottom(false);
            }
            //更新窗口布局
            moveStackWindowsLocked(displayContent);
        }
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

2.1.2 WMS.addAppToken

public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
        int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
        int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
    long inputDispatchingTimeoutNanos;
    inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;

    synchronized(mWindowMap) {
        AppWindowToken atoken = findAppWindowToken(token.asBinder());
        ...
        //创建AppWindowToken对象
        atoken = new AppWindowToken(this, token, voiceInteraction);
        atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
        atoken.appFullscreen = fullscreen;
        atoken.showForAllUsers = showForAllUsers;
        atoken.requestedOrientation = requestedOrientation;
        atoken.layoutConfigChanges = (configChanges &
                (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
        atoken.mLaunchTaskBehind = launchTaskBehind;

        //获取或创建相应的Task
        Task task = mTaskIdToTask.get(taskId);
        if (task == null) {
            task = createTaskLocked(taskId, stackId, userId, atoken);
        }
        task.addAppToken(addPos, atoken);
        //将该Token添加到mTokenMap
        mTokenMap.put(token.asBinder(), atoken);

        atoken.hidden = true;
        atoken.hiddenRequested = true;
    }
}

该方法的主要功能:创建AppWindowToken对象atoken,并添加到mTokenMap。另外,input超时时长为5s.

2.1.3 WMS.prepareAppTransition

public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
    synchronized(mWindowMap) {
        if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
            mAppTransition.setAppTransition(transit);
        } else if (!alwaysKeepCurrent) {
            if (transit == AppTransition.TRANSIT_TASK_OPEN
                    && mAppTransition.isTransitionEqual(
                            AppTransition.TRANSIT_TASK_CLOSE)) {
                //正在打开新的task,取代关闭动画
                mAppTransition.setAppTransition(transit);
            } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
                    && mAppTransition.isTransitionEqual(
                        AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
                //正在打开新的activity,取代关闭动画
                mAppTransition.setAppTransition(transit);
            }
        }
        if (okToDisplay() && mAppTransition.prepare()) {
            mSkipAppTransitionAnimation = false;
        }
        if (mAppTransition.isTransitionSet()) {
            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
            mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
        }
    }
}

2.1.4 WMS.setAppStartingWindow

public void setAppStartingWindow(IBinder token, String pkg,
        int theme, CompatibilityInfo compatInfo,
        CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
        int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
    ...
    wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
                        labelRes, icon, logo, windowFlags);
    Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
    mH.sendMessageAtFrontOfQueue(m);
}

该方法的主要功能是创建startingData启动数据,并发送消息到”android.display”线程来处理ADD_STARTING消息

2.2 AS.resumeTopActivityInnerLocked

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    final ActivityRecord next = topRunningActivityLocked(null);
    ...
    //暂停上一个Activity
    boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
    
    //进程已存在的情况
    if (next.app != null && next.app.thread != null) {
        //activity正在成为可见[见小节2.2.1]
        mWindowManager.setAppVisibility(next.appToken, true);
        ...

        ArrayList<ResultInfo> a = next.results;
        if (a != null) {
            final int N = a.size();
            if (!next.finishing && N > 0) {
                next.app.thread.scheduleSendResult(next.appToken, a);
            }
        }

        if (next.newIntents != null) {
            next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
        }

        next.sleeping = false;
        mService.showAskCompatModeDialogLocked(next);
        next.app.pendingUiClean = true;
        next.app.forceProcessStateUpTo(mService.mTopProcessState);
        next.clearOptionsLocked();
        //触发onResume 
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                mService.isNextTransitionForward(), resumeAnimOptions);

        mStackSupervisor.checkReadyForSleepLocked();
    }else {
        ...
        //目标Activity所属的进程不存在的情况
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
}

resumeTopActivityInnerLocke的过程分两种情况:

  1. 当目标Activity所属的进程已创建,则下一步调用到AT.scheduleResumeActivity;
  2. 当目标Activity所属的进程未创建,则先创建进程后,再调用AT.scheduleLaunchActivity;

2.2.1 WMS.setAppVisibility

public void setAppVisibility(IBinder token, boolean visible) {
    AppWindowToken wtoken;

    synchronized(mWindowMap) {
        //从mTokenMap找到相应的Token对象
        wtoken = findAppWindowToken(token);
        mOpeningApps.remove(wtoken);
        mClosingApps.remove(wtoken);
        wtoken.waitingToShow = false;
        wtoken.hiddenRequested = !visible;

        if (okToDisplay() && mAppTransition.isTransitionSet()) {
            //设置用于占位的动画
            if (!wtoken.mAppAnimator.usingTransferredAnimation &&
                    (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) {
                wtoken.mAppAnimator.setDummyAnimation();
            }
            wtoken.inPendingTransaction = true;
            if (visible) {
                mOpeningApps.add(wtoken);
                wtoken.startingMoved = false;
                wtoken.mEnteringAnimation = true;

                if (wtoken.hidden) {
                    wtoken.allDrawn = false;
                    wtoken.deferClearAllDrawn = false;
                    wtoken.waitingToShow = true;

                    if (wtoken.clientHidden) {
                        wtoken.clientHidden = false;
                        wtoken.sendAppVisibilityToClients();
                    }
                }
            } else {
                mClosingApps.add(wtoken);
                wtoken.mEnteringAnimation = false;
            }
            if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
                //后台启动的,则将启动中的Activity添加到mOpeningApps.
                final WindowState win = findFocusedWindowLocked(getDefaultDisplayContentLocked());
                if (win != null) {
                    final AppWindowToken focusedToken = win.mAppToken;
                    if (focusedToken != null) {
                        //强制加载动画
                        focusedToken.hidden = true;
                        mOpeningApps.add(focusedToken);
                    }
                }
            }
            return;
        }

        final long origId = Binder.clearCallingIdentity();
        wtoken.inPendingTransaction = false;
        //设置AppWindowToken相应窗口可见
        setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
                true, wtoken.voiceInteraction);
        wtoken.updateReportedVisibilityLocked();
        Binder.restoreCallingIdentity(origId);
    }
}

2.3 AT.handleLaunchActivity

scheduleLaunchActivity之后便调用到了handleLaunchActivity方法

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    handleConfigurationChanged(null, null);
    //初始化WMS【见小节2.3.1】
    WindowManagerGlobal.initialize();
    //【见小节2.4】
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        //【见小节2.5】
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);
        ...
    }
    ...
}

2.3.1 WMS.initialize

public static void initialize() {
    getWindowManagerService();
}
   
public static IWindowManager getWindowManagerService() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowManagerService == null) {
            //获取AMS的binder代理
            sWindowManagerService = IWindowManager.Stub.asInterface(
                    ServiceManager.getService("window"));
            sWindowManagerService = getWindowManagerService();
            ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
        }
        return sWindowManagerService;
    }
}

该方法的功能是获取AMS的binder代理。

2.4 AT.performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        //创建LoadedApk对象
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }

    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
            mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }

    if (r.activityInfo.targetActivity != null) {
        //创建ComponentName对象
        component = new ComponentName(r.activityInfo.packageName,
                r.activityInfo.targetActivity);
    }

    Activity activity = null;
    //获取ClassLoader
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    //创建目标Activity对象
    activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    StrictMode.incrementExpectedActivityCount(activity.getClass());
    r.intent.setExtrasClassLoader(cl);
    r.intent.prepareToEnterProcess();
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }

    //创建Application对象
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    if (activity != null) {
        Context appContext = createBaseContextForActivity(r, activity);
        CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
        Configuration config = new Configuration(mCompatConfiguration);
        //变量赋值操作【见小节2.4.1】
        activity.attach(appContext, this, getInstrumentation(), r.token,
                r.ident, app, r.intent, r.activityInfo, title, r.parent,
                r.embeddedID, r.lastNonConfigurationInstances, config,
                r.referrer, r.voiceInteractor);
        ...
        //【见小节2.4.2】
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
        ...
        
        if (!r.activity.mFinished) {
            if (r.isPersistable()) {
                if (r.state != null || r.persistentState != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                            r.persistentState);
                }
            } else if (r.state != null) {
                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
            }
        }
        ...
    }
    r.paused = true;
    mActivities.put(r.token, r);
    return activity;
}

该方法主要功能:

  1. 创建LoadedApk对象;
  2. 创建ComponentName对象;
  3. 获取ClassLoader;
  4. 创建目标Activity对象;
  5. 创建Application对象;
  6. 回调onCreate(),一般地该方法内执行setContentView()操作;

2.4.1 Activity.attach

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    attachBaseContext(context);
    mFragments.attachHost(null /*parent*/);

    mWindow = new PhoneWindow(this); //创建PhoneWindow
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    ...
    mUiThread = Thread.currentThread(); //获取UI线程
    mMainThread = aThread;
    mInstrumentation = instr;
    mToken = token; //远程ActivityRecord的appToken的代理端
    mIdent = ident;
    mApplication = application; //所属的Appplication
    mIntent = intent;
    mReferrer = referrer;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mParent = parent;
    ...
    //设置并获取WindowManagerImpl对象
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
        mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();
    mCurrentConfig = config;
}

该方法主要功能是完成以下成员变量的赋值:

  • mWindow:数据类型为PhoneWindow,继承于Window对象;
  • mWindowManager:数据类型为WindowManagerImpl,实现WindowManager接口;
  • mMainThread:当前线程的ActivityThread对象;
  • mApplication:当前Activity所属的Application;
  • mHandler:当前主线程的handler;
  • mUiThread: 当前activity所在的主线程;
  • mToken:远程ActivityRecord的appToken的代理端
  • mDecor: Activity执行完resume之后创建的View对象;

WindowManagerImpl.mParentWindowWindow指向Window对象, Window.mWindowManager指向WindowManagerImpl对象,这两个对象相互保存对方的信息。

2.5 AT.handleResumeActivity

final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume) {
    //[见小节2.5.1]
    ActivityClientRecord r = performResumeActivity(token, clearHide);

    if (r != null) {
        final Activity a = r.activity;
        boolean willBeVisible = !a.mStartedActivity;
        ...
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (a.mVisibleFromClient) {
                a.mWindowAdded = true;
                wm.addView(decor, l);
            }

        }
        ...
        if (!r.activity.mFinished && willBeVisible
                && r.activity.mDecor != null && !r.hideForNow) {
            ...
            mNumVisibleActivities++;
            if (r.activity.mVisibleFromClient) {
                r.activity.makeVisible(); //[见小节2.5.2]
            }
        }

        //resume完成
        if (reallyResume) {
              ActivityManagerNative.getDefault().activityResumed(token);
        }
    } else {
        ...
    }
}

2.5.1 AT.performResumeActivity

public final ActivityClientRecord performResumeActivity(IBinder token,
        boolean clearHide) {
    ActivityClientRecord r = mActivities.get(token);
    if (r != null && !r.activity.mFinished) {
        if (clearHide) {
            r.hideForNow = false;
            r.activity.mStartedActivity = false;
        }
        r.activity.onStateNotSaved();
        r.activity.mFragments.noteStateNotSaved();
        if (r.pendingIntents != null) {
            deliverNewIntents(r, r.pendingIntents);
            r.pendingIntents = null;
        }
        if (r.pendingResults != null) {
            deliverResults(r, r.pendingResults);
            r.pendingResults = null;
        }
        //回调onResume
        r.activity.performResume();
        ...
    }
    return r;
}

2.5.2 Activity.makeVisible

void makeVisible() {
    if (!mWindowAdded) {
        ViewManager wm = getWindowManager();
        //【见小节2.6】
        wm.addView(mDecor, getWindow().getAttributes());
        mWindowAdded = true;
    }
    mDecor.setVisibility(View.VISIBLE);
}

2.6 WMI.addView

[-> WindowManagerImpl.java]

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    //【见小节2.6.1】
    mGlobal.addView(view, params, mDisplay, mParentWindow);
}

2.6.1 WMG.addView

[-> WindowManagerGlobal.java]

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    ...
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    //创建ViewRootImpl[见小节2.7]
    ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
    view.setLayoutParams(wparams);
    mViews.add(view);
    mRoots.add(root);
    mParams.add(wparams);
    
    //[见小节2.8]
    root.setView(view, wparams, panelParentView);
    ...
}

2.7 ViewRootImpl

[-> ViewRootImpl.java]

public ViewRootImpl(Context context, Display display) {
    mContext = context;
    //获取IWindowSession的代理类【见小节2.7.1】
    mWindowSession = WindowManagerGlobal.getWindowSession();
    mDisplay = display;
    mThread = Thread.currentThread(); //主线程
    mWindow = new W(this); //【见小节2.7.3】
    mChoreographer = Choreographer.getInstance();
    ...
}

初始化成员变量:

  • mWindowSession:WMS端的Session的代理对象;
  • mWindow: 继承于IWindow.Stub的W对象;
  • mChoreographer:绘制相关的对象;

2.7.1 getWindowSession

[-> WindowManagerGlobal.java]

public static IWindowSession getWindowSession() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowSession == null) {
            try {
                //获取IMS的代理类
                InputMethodManager imm = InputMethodManager.getInstance();
                //获取WMS的代理类
                IWindowManager windowManager = getWindowManagerService();
                //经过Binder调用,最终调用WMS[见小节2.7.2]
                sWindowSession = windowManager.openSession(
                        new IWindowSessionCallback.Stub() {...},
                        imm.getClient(), imm.getInputContext());
            } catch (RemoteException e) {
                ...
            }
        }
        return sWindowSession
    }
}

通过binder调用进入system_server进程,执行如下操作:

2.7.2 WMS.openSession

public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
        IInputContext inputContext) {
    //创建Session对象
    Session session = new Session(this, callback, client, inputContext);
    return session;
}

再次经过Binder将数据写回app进程,则获取的便是Session的代理对象。

2.7.3 IWindow.Stub

[-> ViewRootImpl.java ::W]

static class W extends IWindow.Stub {
    private final WeakReference<ViewRootImpl> mViewAncestor;
    private final IWindowSession mWindowSession;

    W(ViewRootImpl viewAncestor) {
        mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
        mWindowSession = viewAncestor.mWindowSession;
    }
    ...
}

2.8 setView

[-> ViewRootImpl.java]

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
  synchronized (this) {
    ...
    //通过Binder调用,进入system进程的Session[见小节2.9]
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
          getHostVisibility(), mDisplay.getDisplayId(),
          mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
          mAttachInfo.mOutsets, mInputChannel);
    ...
  }
}

通过Binder调用,进入system进程的Session对象

2.9 Session.addToDisplay

[-> Session.java]

final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {

    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
            Rect outOutsets, InputChannel outInputChannel) {
        //[见小节2.9.1]
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }
}

2.9.1 WMS.addWindow

[-> WindowManagerService.java]

public int addWindow(Session session, IWindow client, int seq,
           WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
           Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
           InputChannel outInputChannel) {
    ...
    WindowToken token = mTokenMap.get(attrs.token);
    //创建WindowState【见小节2.9.2】
    WindowState win = new WindowState(this, session, client, token,
                attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
    ...
    mPolicy.adjustWindowParamsLw(win.mAttrs);
    res = mPolicy.prepareAddWindowLw(win, attrs);
    addWindowToListInOrderLocked(win, true);
    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                    false /*updateInputWindows*/);
    assignLayersLocked(displayContent.getWindowList());
    ...
}

2.9.2 WindowState

[-> WindowState.java]

WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
       WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
       int viewVisibility, final DisplayContent displayContent) {
    mService = service;
    mSession = s; //Session的Binder服务端
    mClient = c;  //IWindow的Binder代理端
    mToken = token;
    mOwnerUid = s.mUid; //所对应app的uid
    ...
    DeathRecipient deathRecipient = new DeathRecipient();
    c.asBinder().linkToDeath(deathRecipient, 0); //app端死亡则会有死亡回调
    
    WindowState appWin = this;
    WindowToken appToken = appWin.mToken;
    while (appToken.appWindowToken == null) {
       WindowToken parent = mService.mTokenMap.get(appToken.token);
       if (parent == null || appToken == parent) {
           break;
       }
       appToken = parent;
    }
    mAppToken = appToken.appWindowToken;
    
    //创建WindowStateAnimator对象
    mWinAnimator = new WindowStateAnimator(this);
    //创建InputWindowHandle对象
    mInputWindowHandle = new InputWindowHandle(
            mAppToken != null ? mAppToken.mInputApplicationHandle : null, this,
            displayContent.getDisplayId());
}

WindowState持有远程app进程中IWindow.Stub的代理镀锡,并且注册了死亡回调,当app进程死亡则会收到相应的死亡通知。

三. 总结

Activity的启动过程同时贯穿着AMS/WMS相关信息的创建,本文从Window角度来看待整个过程:

第一阶段运行在system_server进程:

  1. 将Window相应task移至顶部,并创建AppWindowToken对象,添加到WMS.mTokenMap记录该信息;
  2. 发送消息到”android.display”线程来处理ADD_STARTING启动窗口的消息。

第二阶段运行在目标进程的主线程:(当然在该阶段有些方法会Binder call到system_server进程)

  1. 创建获取AMS的binder代理;
  2. 执行performLaunchActivity过程,创建如下对象:
    • 创建LoadedApk对象;
    • 创建ComponentName对象;
    • 创建目标Activity对象;
    • 创建Application对象;
  3. 创建完Activity,执行attach操作,初始化成员变量:
    • mWindow:数据类型为PhoneWindow,继承于Window对象;
    • mWindowManager:数据类型为WindowManagerImpl,实现WindowManager接口;
    • mToken:远程ActivityRecord的appToken的代理端
  4. 执行performResumeActivity过程;
  5. 执行addView过程:
    • 创建ViewRootImpl对象;
    • 创建WMS端的Session的代理对象;
    • 创建继承于IWindow.Stub的ViewRootImpl.W对象; - setView()添加视图到WMS
    • 在WMS中创建WindowState对象。

理解JobScheduler机制

$
0
0

一. 概述

对于满足网络、电量、时间等一定预定条件而触发的任务,那么jobScheduler便是绝佳选择。JobScheduler主要用于在未来某个时间下满足一定条件时触发执行某项任务的情况,那么可以创建一个JobService的子类,重写其onStartJob()方法来实现这个功能。

JobScheduler的schedule过程:

 JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);  
 ComponentName jobService = new ComponentName(this, MyJobService.class); 
 
 JobInfo jobInfo = new JobInfo.Builder(123, jobService) //任务Id等于123
         .setMinimumLatency(5000)// 任务最少延迟时间  
         .setOverrideDeadline(60000)// 任务deadline,当到期没达到指定条件也会开始执行  
         .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)// 网络条件,默认值NETWORK_TYPE_NONE
         .setRequiresCharging(true)// 是否充电  
         .setRequiresDeviceIdle(false)// 设备是否空闲 
         .setPersisted(true) //设备重启后是否继续执行
         .setBackoffCriteria(3000,JobInfo.BACKOFF_POLICY_LINEAR) //设置退避/重试策略
         .build();  
 scheduler.schedule(jobInfo); 

JobScheduler的cancel过程:

 scheduler.cancel(123); //取消jobId=123的任务
 scheduler.cancelAll(); //取消当前uid下的所有任务

schedule过程说明:

  1. 先获取JobScheduler调度器的代理对象,要理解这个过程,那么就需要先看看JobSchedulerService的启动过程;
  2. 创建继承于JobService的对象,见小节3.2;
  3. 创建JobInfo对象,采用builder模式;
  4. 调用schedule()来调度任务,见小节3.3。

接下来,先来看看JobSchedulerService启动过程。

二. JobScheduler服务启动

2.1 startOtherServices

[-> SystemServer.java]

private void startOtherServices() {
  ...
  mSystemServiceManager.startService(JobSchedulerService.class);
  ...
}

该方法先初始化JSS,然后再调用其onStart()方法。

2.2 JobSchedulerService

[-> JobSchedulerService.java]

JobSchedulerService {
    List<StateController> mControllers;
    final JobHandler mHandler;
    final JobSchedulerStub mJobSchedulerStub;
    final JobStore mJobs;
    ...
    
    public JobSchedulerService(Context context) {
        super(context);
        mControllers = new ArrayList<StateController>();
        mControllers.add(ConnectivityController.get(this));
        mControllers.add(TimeController.get(this));
        mControllers.add(IdleController.get(this));
        mControllers.add(BatteryController.get(this));
        mControllers.add(AppIdleController.get(this));
        
        //创建主线程的looper[见小节2.3]
        mHandler = new JobHandler(context.getMainLooper());
        //创建binder服务端[见小节2.4]
        mJobSchedulerStub = new JobSchedulerStub();
        //[见小节2.5]
        mJobs = JobStore.initAndGet(this);
    }

    public void onStart() {
        publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
    }
}

创建了5个不同的StateController,分别添加到mControllers。

类型说明
ConnectivityController注册监听网络连接状态的广播
TimeController注册监听job时间到期的广播
IdleController注册监听屏幕亮/灭,dream进入/退出,状态改变的广播
BatteryController注册监听电池是否充电,电量状态的广播
AppIdleController监听app是否空闲

state_controller

接下来,以ConnectivityController为例,说一说相应Controller的创建过程, 其他Controller也基本类似.

2.2.1 ConnectivityController

[-> ConnectivityController.java]

public class ConnectivityController extends StateController implements
        ConnectivityManager.OnNetworkActiveListener {
        
    public static ConnectivityController get(JobSchedulerService jms) {
        synchronized (sCreationLock) {
            if (mSingleton == null) {
                //单例模式
                mSingleton = new ConnectivityController(jms, jms.getContext());
            }
            return mSingleton;
        }
    }
    
    private ConnectivityController(StateChangedListener stateChangedListener, Context context) {
        super(stateChangedListener, context);
        //注册监听网络连接状态的广播,且采用BackgroundThread线程
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiverAsUser(
                mConnectivityChangedReceiver, UserHandle.ALL, intentFilter, null,
                BackgroundThread.getHandler());
        ConnectivityService cs =
                (ConnectivityService)ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
        if (cs != null) {
            if (cs.getActiveNetworkInfo() != null) {
                mNetworkConnected = cs.getActiveNetworkInfo().isConnected();
            }
            mNetworkUnmetered = mNetworkConnected && !cs.isActiveNetworkMetered();
        }
    }
}

当监听到CONNECTIVITY_ACTION广播,onReceive方法的执行位于“android.bg”线程。

2.3 JSS.JobHandler

[-> JobSchedulerService.java ::JobHandler]

public class JobSchedulerService extends com.android.server.SystemService
    implements StateChangedListener, JobCompletedListener {
    private class JobHandler extends Handler {

    public JobHandler(Looper looper) {
        super(looper);
    }

    public void handleMessage(Message message) {
        synchronized (mJobs) {
            //当系统启动到phase 600,则mReadyToRock=true.
            if (!mReadyToRock) {
                return;
            }
        }
        switch (message.what) {
            case MSG_JOB_EXPIRED: ...
            case MSG_CHECK_JOB: ...
        }
        maybeRunPendingJobsH();
        removeMessages(MSG_CHECK_JOB);
    }

JobHandler采用的是system_server进程的主线程Looper,也就是该过程运行在主线程。

2.4 JobSchedulerStub

[-> JobSchedulerService.java ::JobSchedulerStub]

final class JobSchedulerStub extends IJobScheduler.Stub {
    ...
}

JobSchedulerStub作为实现接口IJobScheduler的binder服务端。

2.5 JS.initAndGet

[-> JobStore.java]

static JobStore initAndGet(JobSchedulerService jobManagerService) {
    synchronized (sSingletonLock) {
        if (sSingleton == null) {
            //[见小节2.6]
            sSingleton = new JobStore(jobManagerService.getContext(),
                    Environment.getDataDirectory());
        }
        return sSingleton;
    }
}

2.6 创建JobStore

[-> JobStore.java]

public class JobStore {
    final ArraySet<JobStatus> mJobSet;
    private final Handler mIoHandler = IoThread.getHandler();
    ...
    
    private JobStore(Context context, File dataDir) {
        mContext = context;
        mDirtyOperations = 0;

        File systemDir = new File(dataDir, "system");
        File jobDir = new File(systemDir, "job");
        jobDir.mkdirs();
        // 创建/data/system/job/jobs.xml
        mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"));
        mJobSet = new ArraySet<JobStatus>();
        //[见小节2.7.1]
        readJobMapFromDisk(mJobSet);
    }
}

该方法会创建job目录以及jobs.xml文件, 以及从文件中读取所有的JobStatus。

2.7 xml解析

2.7.1 ReadJobMapFromDiskRunnable

[-> JobStore.java]

private class ReadJobMapFromDiskRunnable implements Runnable {
    private final ArraySet<JobStatus> jobSet;

    ReadJobMapFromDiskRunnable(ArraySet<JobStatus> jobSet) {
        this.jobSet = jobSet;
    }

    public void run() {
        List<JobStatus> jobs;
        FileInputStream fis = mJobsFile.openRead();
        synchronized (JobStore.this) {
            jobs = readJobMapImpl(fis);  //[见小节2.7.2]
            if (jobs != null) {
                for (int i=0; i<jobs.size(); i++) {
                    this.jobSet.add(jobs.get(i));
                }
            }
        }
        fis.close();
    }
}

此处mJobsFile便是/data/system/job/jobs.xml。

2.7.2 readJobMapImpl

[-> JobStore.java]

private List<JobStatus> readJobMapImpl(FileInputStream fis)
         throws XmlPullParserException, IOException {
     XmlPullParser parser = Xml.newPullParser();
     parser.setInput(fis, StandardCharsets.UTF_8.name());
     ...

     String tagName = parser.getName();
     if ("job-info".equals(tagName)) {
         final List<JobStatus> jobs = new ArrayList<JobStatus>();
         ...
         eventType = parser.next();
         do {
             //读取每一个 <job/>
             if (eventType == XmlPullParser.START_TAG) {
                 tagName = parser.getName();
                 if ("job".equals(tagName)) {
                      //[见小节2.7.3]
                     JobStatus persistedJob = restoreJobFromXml(parser);
                     if (persistedJob != null) {
                         jobs.add(persistedJob);
                     } 
                 }
             }
             eventType = parser.next();
         } while (eventType != XmlPullParser.END_DOCUMENT);
         return jobs;
     }
     return null;
 }

从文件jobs.xml中读取并创建JobStatus,然后添加到mJobSet.

2.7.3 restoreJobFromXml

[-> JobStore.java]

private JobStatus restoreJobFromXml(XmlPullParser parser) throws XmlPullParserException,
            IOException {
    JobInfo.Builder jobBuilder;
    int uid;
    //创建用于获取jobInfo的Builder[见小节2.7.4]
    jobBuilder = buildBuilderFromXml(parser);
    jobBuilder.setPersisted(true);
    uid = Integer.valueOf(parser.getAttributeValue(null, "uid"));
    ...
    
    buildConstraintsFromXml(jobBuilder, parser); //读取常量
    //读取job执行的两个时间点:delay和deadline
    Pair<Long, Long> elapsedRuntimes = buildExecutionTimesFromXml(parser);
    ...
    //[见小节2.8]
    return new JobStatus(jobBuilder.build(), uid, 
                elapsedRuntimes.first, elapsedRuntimes.second);
}

2.7.4 buildBuilderFromXml

[-> JobStore.java]

private JobInfo.Builder buildBuilderFromXml(XmlPullParser parser) throws NumberFormatException {
    int jobId = Integer.valueOf(parser.getAttributeValue(null, "jobid"));
    String packageName = parser.getAttributeValue(null, "package");
    String className = parser.getAttributeValue(null, "class");
    ComponentName cname = new ComponentName(packageName, className);
    //[见小节2.7.5]
    return new JobInfo.Builder(jobId, cname);
}

创建的JobInfo对象,记录着任务的jobid, package, class。

2.7.5 创建JobInfo

[-> JobInfo.java]

public class JobInfo implements Parcelable {
    public static final class Builder {
        public Builder(int jobId, ComponentName jobService) {
             mJobService = jobService;
             mJobId = jobId;
        }
        public JobInfo build() {
            mExtras = new PersistableBundle(mExtras); 
            return new JobInfo(this); //创建JobInfo
        }
    }
}

2.8 创建JobStatus

[-> JobStatus.java]

public JobStatus(JobInfo job, int uId, long earliestRunTimeElapsedMillis,
                  long latestRunTimeElapsedMillis) {
    this(job, uId, 0);

    this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis;
    this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis;
}

private JobStatus(JobInfo job, int uId, int numFailures) {
    this.job = job;
    this.uId = uId;
    this.name = job.getService().flattenToShortString();
    this.tag = "*job*/" + this.name;
    this.numFailures = numFailures;
}

JobStatus对象记录着任务的jobId, ComponentName, uid以及标签和失败次数信息。

2.9 JSS.onBootPhase

public void onBootPhase(int phase) {
    if (PHASE_SYSTEM_SERVICES_READY == phase) {
        //阶段500,则开始注册package和use移除的广播监听
        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
        filter.addDataScheme("package");
        getContext().registerReceiverAsUser(
                mBroadcastReceiver, UserHandle.ALL, filter, null, null);
        final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
        userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
        getContext().registerReceiverAsUser(
                mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
        mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
    } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
        synchronized (mJobs) {
            mReadyToRock = true;
            mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
                    BatteryStats.SERVICE_NAME));
            for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
                //创建JobServiceContext对象
                mActiveServices.add(
                        new JobServiceContext(this, mBatteryStats,
                                getContext().getMainLooper()));
            }
            ArraySet<JobStatus> jobs = mJobs.getJobs();
            for (int i=0; i<jobs.size(); i++) {
                JobStatus job = jobs.valueAt(i);
                for (int controller=0; controller<mControllers.size(); controller++) {
                    mControllers.get(controller).deviceIdleModeChanged(mDeviceIdleMode);
                    mControllers.get(controller).maybeStartTrackingJob(job);
                }
            }
            mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
        }
    }
}

对于低内存的设备,则只创建一个创建JobServiceContext对象;否则创建3个该对象。

2.9.1 创建JobServiceContext

[-> JobServiceContext.java]

JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats, Looper looper) {
    this(service.getContext(), batteryStats, service, looper);
}

JobServiceContext(Context context, IBatteryStats batteryStats,
        JobCompletedListener completedListener, Looper looper) {
    mContext = context;
    mBatteryStats = batteryStats;
    mCallbackHandler = new JobServiceHandler(looper);
    mCompletedListener = completedListener;
    mAvailable = true;
}

此处的JobServiceHandler采用的是system_server进程的主线程。

2.10 小结

  1. JSS.JobHandler运行在system_server进程的主线程;
  2. JobServiceContext.JobServiceHandler运行在system_server进程的主线程;
  3. JobSchedulerStub作为实现接口IJobScheduler的binder服务端;
  4. JobStore:其成员变量mIoHandler运行在”android.io”线程;
  5. JobStatus:从/data/system/job/jobs.xml文件中读取每个JobInfo,再解析成JobStatus对象,添加到mJobSet。

可见JobSchedulerService启动过程,最主要工作是从jobs.xml文件收集所有的jobs,放入到JobStore的成员变量mJobSet。接下来,再回到文章最开头,来说一说schedule过程。

三. Schedule

3.1 JobScheduler

[-> SystemServiceRegistry]

registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
        new StaticServiceFetcher<JobScheduler>() {
    public JobScheduler createService() {
        IBinder b = ServiceManager.getService(Context.JOB_SCHEDULER_SERVICE);
        return new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b));
    }});

从这个过程,可知客户端请求获取JOB_SCHEDULER_SERVICE服务, 返回的是JobSchedulerImpl对象.JobSchedulerImpl对象继承于JobScheduler对象.

3.2 JobService

[-> JobService.java]

public abstract class JobService extends Service {
    IJobService mBinder = new IJobService.Stub() {
        public void startJob(JobParameters jobParams) {
            ensureHandler();
            //向主线程的Handler发送执行任务的消息
            Message m = Message.obtain(mHandler, MSG_EXECUTE_JOB, jobParams);
            m.sendToTarget();
        }
        public void stopJob(JobParameters jobParams) {
            ensureHandler();
            //向主线程的Handler发送停止任务的消息
            Message m = Message.obtain(mHandler, MSG_STOP_JOB, jobParams);
            m.sendToTarget();
        }
    };
    
    void ensureHandler() {
       synchronized (mHandlerLock) {
           if (mHandler == null) {
               //[见小节3.2.1]
               mHandler = new JobHandler(getMainLooper());
           }
       }
   }
   public final IBinder onBind(Intent intent) {
      return mBinder.asBinder();
  }
  
}

由于JobService运行在app端所在进程,那么此处的mHandler便是指app进程的主线程。

3.2.1 JS.JobHandler

[-> JobService.java ::JobHandler]

class JobHandler extends Handler {
    ...
    public void handleMessage(Message msg) {
        final JobParameters params = (JobParameters) msg.obj;
        switch (msg.what) {
            case MSG_EXECUTE_JOB:
                boolean workOngoing = JobService.this.onStartJob(params);
                ackStartMessage(params, workOngoing);
                break;
            case MSG_STOP_JOB:
                boolean ret = JobService.this.onStopJob(params);
                ackStopMessage(params, ret);
                break;
            case MSG_JOB_FINISHED:
                final boolean needsReschedule = (msg.arg2 == 1);
                IJobCallback callback = params.getCallback();
                if (callback != null) {
                    callback.jobFinished(params.getJobId(), needsReschedule);
                }
                break;
            default:
                break;
        }
    }
}    

对于启动和停止任务,都分别向主线程发送消息,则分别会回调onStartJob和onStopJob方法。 由小节3.1 可知获取代理对象为JobSchedulerImpl,接下来说一说JobSchedulerImpl的schedule 过程。

3.3 JSI.schedule

[-> JobSchedulerImpl.java]

public int schedule(JobInfo job) {
    try {
        return mBinder.schedule(job); //[见小节3.4]
    } catch (RemoteException e) {
        return JobScheduler.RESULT_FAILURE;
    }
}

当app端调用JobSchedulerImpl的schedule()过程,通过binder call进入了system_server的binder线程,进入如下操作.

3.4 JobSchedulerStub.schedule

[-> JobSchedulerService.java ::JobSchedulerStub]

public int schedule(JobInfo job) throws RemoteException {
    final int pid = Binder.getCallingPid();
    final int uid = Binder.getCallingUid();
    enforceValidJobRequest(uid, job);

    long ident = Binder.clearCallingIdentity();
    try {
        return JobSchedulerService.this.schedule(job, uid);  //[见小节3.5]
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}

3.5 JSS.schedule

public int schedule(JobInfo job, int uId) {
    //创建JobStatus
    JobStatus jobStatus = new JobStatus(job, uId);
    //先取消该uid下的任务【见小节3.6】
    cancelJob(uId, job.getId());
    //开始追踪该任务【见小节3.7】
    startTrackingJob(jobStatus);
    //向system_server进程的主线程发送message.【见小节3.8】
    mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
    return JobScheduler.RESULT_SUCCESS;
}

3.6 JSS.cancelJob

[-> JobSchedulerService.java]

public void cancelJob(int uid, int jobId) {
    JobStatus toCancel;
    synchronized (mJobs) {
        //查找到相应的JobStatus
        toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
    }
    if (toCancel != null) {
        //【见小节4.3】
        cancelJobImpl(toCancel);
    }
}

3.7 JSS.startTrackingJob

private void startTrackingJob(JobStatus jobStatus) {
    boolean update;
    boolean rocking;
    synchronized (mJobs) {
        update = mJobs.add(jobStatus);
        rocking = mReadyToRock;
    }
    if (rocking) {
        for (int i=0; i<mControllers.size(); i++) {
            StateController controller = mControllers.get(i);
            if (update) {
                controller.maybeStopTrackingJob(jobStatus);
            }
            controller.maybeStartTrackingJob(jobStatus);
        }
    }
}

先将该JobStatus添加到JobStore,再遍历已添加的5个状态控制器, 依次检查是否需要将该任务添加到相应的追踪控制器. 再回到[小节3.5],通过JobHandler发送MSG_CHECK_JOB消息,接下来进入其handleMessage。

3.8 JSS.JobHandler

[-> JobSchedulerService.java ::JobHandler]

private class JobHandler extends Handler {
    public void handleMessage(Message message) {
        synchronized (mJobs) {
            if (!mReadyToRock) {
                return;
            }
        }
        switch (message.what) {
            case MSG_JOB_EXPIRED: ...                    
                break;
            case MSG_CHECK_JOB:
                synchronized (mJobs) {
                    //[见小节3.9]
                    maybeQueueReadyJobsForExecutionLockedH();
                }
                break;
        }
        //[见小节3.10]
        maybeRunPendingJobsH();
        removeMessages(MSG_CHECK_JOB);
    }
}

3.9 maybeQueueReadyJobsForExecutionLockedH

[-> JobSchedulerService.java ::JobHandler]

private void maybeQueueReadyJobsForExecutionLockedH() {
    int chargingCount = 0;
    int idleCount =  0;
    int backoffCount = 0;
    int connectivityCount = 0;
    List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
    ArraySet<JobStatus> jobs = mJobs.getJobs();
    for (int i=0; i<jobs.size(); i++) {
        JobStatus job = jobs.valueAt(i);
        if (isReadyToBeExecutedLocked(job)) {
            if (job.getNumFailures() > 0) {
                backoffCount++;
            }
            if (job.hasIdleConstraint()) {
                idleCount++;
            }
            if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
                connectivityCount++;
            }
            if (job.hasChargingConstraint()) {
                chargingCount++;
            }
            //将所有job加入runnableJobs队列
            runnableJobs.add(job);
        } else if (isReadyToBeCancelledLocked(job)) {
            stopJobOnServiceContextLocked(job);
        }
    }
    if (backoffCount > 0 ||
            idleCount >= MIN_IDLE_COUNT ||
            connectivityCount >= MIN_CONNECTIVITY_COUNT ||
            chargingCount >= MIN_CHARGING_COUNT ||
            runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
        for (int i=0; i<runnableJobs.size(); i++) {
            //加入到mPendingJobs队列
            mPendingJobs.add(runnableJobs.get(i));
        }
    } 
}

该功能:

  1. 先将所有JobStatus加入runnableJobs队列;
  2. 再将runnableJobs中满足触发条件的JobStatus加入到mPendingJobs队列;

3.10 maybeRunPendingJobsH

private void maybeRunPendingJobsH() {
    synchronized (mJobs) {
        if (mDeviceIdleMode) {
            return;
        }
        Iterator<JobStatus> it = mPendingJobs.iterator();
        while (it.hasNext()) {
            JobStatus nextPending = it.next();
            JobServiceContext availableContext = null;
            for (int i=0; i<mActiveServices.size(); i++) {
                JobServiceContext jsc = mActiveServices.get(i);
                final JobStatus running = jsc.getRunningJob();
                if (running != null && running.matches(nextPending.getUid(),
                        nextPending.getJobId())) {
                    availableContext = null;
                    break;
                }
                if (jsc.isAvailable()) {
                    availableContext = jsc;
                }
            }
            if (availableContext != null) {
                //[见小节3.11]
                if (!availableContext.executeRunnableJob(nextPending)) {
                    mJobs.remove(nextPending);
                }
                it.remove();
            }
        }
    }
}

处理mPendingJobs列队中所有的Job.

3.11 executeRunnableJob

[-> JobServiceContext]

boolean executeRunnableJob(JobStatus job) {
    synchronized (mLock) {
        if (!mAvailable) {
            return false;
        }

        mRunningJob = job;
        final boolean isDeadlineExpired =
                job.hasDeadlineConstraint() &&
                        (job.getLatestRunTimeElapsed() < SystemClock.elapsedRealtime());
        mParams = new JobParameters(this, job.getJobId(), job.getExtras(), isDeadlineExpired);
        mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();

        mVerb = VERB_BINDING;
        scheduleOpTimeOut();
        final Intent intent = new Intent().setComponent(job.getServiceComponent());
        //bind服务【见小节3.11.1】
        boolean binding = mContext.bindServiceAsUser(intent, this,
                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
                new UserHandle(job.getUserId()));
        if (!binding) {
            mRunningJob = null;
            mParams = null;
            mExecutionStartTimeElapsed = 0L;
            mVerb = VERB_FINISHED;
            removeOpTimeOut();
            return false;
        }
        ...
        mAvailable = false;
        return true;
    }
}

这便是由system_server进程的主线程来执行bind Service的方式来拉起的进程,当服务启动后回调到发起端的onServiceConnected。

3.11.1 JSC.onServiceConnected

public void onServiceConnected(ComponentName name, IBinder service) {
    JobStatus runningJob;
    synchronized (mLock) {
        runningJob = mRunningJob;
    }
    if (runningJob == null || !name.equals(runningJob.getServiceComponent())) {
        mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget();
        return;
    }
    //获取远程JobService的代理端
    this.service = IJobService.Stub.asInterface(service);
    ...
    //发送消息【见小节3.11.2】
    mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();
}

this.service是指获取远程IJobService【小节3.2】的代理端,mCallbackHandler运行在system_server的主线程。

3.11.2 MSG_SERVICE_BOUND

[-> JobServiceContext.java]

private class JobServiceHandler extends Handler {
    JobServiceHandler(Looper looper) {
        super(looper);
    }

    public void handleMessage(Message message) {
        switch (message.what) {
            case MSG_SERVICE_BOUND:
                removeOpTimeOut(); //移除MSG_TIMEOUT消息
                handleServiceBoundH(); //【见小节3.11.3】
                break;
            ...
        }
    }
}

3.11.3 JSC.handleServiceBoundH

private void handleServiceBoundH() {
    if (mVerb != VERB_BINDING) {
        closeAndCleanupJobH(false /* reschedule */);
        return;
    }
    if (mCancelled.get()) {
        closeAndCleanupJobH(true /* reschedule */);
        return;
    }
    mVerb = VERB_STARTING;
    scheduleOpTimeOut();
    //此处经过binder调用【见小节3.11.4】
    service.startJob(mParams);
}

此处的service是由【小节3.11.1】所赋值,是指app端IJobService的代理类。经过binder call 回到app进程。

3.11.4 JS.startJob

[-> JobService.java]

public abstract class JobService extends Service {
    IJobService mBinder = new IJobService.Stub() {
        public void startJob(JobParameters jobParams) {
            ensureHandler();
            //向主线程的Handler发送执行任务的消息【见小节3.11.5】
            Message m = Message.obtain(mHandler, MSG_EXECUTE_JOB, jobParams);
            m.sendToTarget();
        }
        
        public void stopJob(JobParameters jobParams) {
            ...
        }
    };
    
  
}

由于JobService运行在app端所在进程,那么此处的mHandler便是指app进程的主线程。

3.11.5 JS.JobHandler

[-> JobService.java ::JobHandler]

class JobHandler extends Handler {
    ...
    public void handleMessage(Message msg) {
        final JobParameters params = (JobParameters) msg.obj;
        switch (msg.what) {
            case MSG_EXECUTE_JOB:
                boolean workOngoing = JobService.this.onStartJob(params);
                ackStartMessage(params, workOngoing);
                break;
            case MSG_STOP_JOB: ...
            case MSG_JOB_FINISHED:...
            default: break;
        }
    }
}   

回到主线程,调用onStartJob()方法。

四. Cancel

4.1 JSI.cancel

[-> JobSchedulerImpl.java]

public class JobSchedulerImpl extends JobScheduler {
    public void cancel(int jobId) {
        try {
            mBinder.cancel(jobId); //【见小节4.2】
        } catch (RemoteException e) {}
    }

    public void cancelAll() {
        try {
            mBinder.cancelAll();
        } catch (RemoteException e) {}
    }
    ...
}

通过binder call,进入system_server的binder线程执行如下操作

4.2 JobSchedulerStub.cancel

[-> JobSchedulerService.java ::JobSchedulerStub]

final class JobSchedulerStub extends IJobScheduler.Stub {
    public void cancel(int jobId) throws RemoteException {
        final int uid = Binder.getCallingUid();
        long ident = Binder.clearCallingIdentity();
        try {
            //【见小节4.3】
            JobSchedulerService.this.cancelJob(uid, jobId);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    
    public void cancelAll() throws RemoteException {
        final int uid = Binder.getCallingUid();
        long ident = Binder.clearCallingIdentity();
        try {
            JobSchedulerService.this.cancelJobsForUid(uid);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    
    ...
}

4.3 JSS.cancelJob

[-> JobSchedulerService.java]

public class JobSchedulerService extends com.android.server.SystemService
        implements StateChangedListener, JobCompletedListener {
        
    public void cancelJob(int uid, int jobId) {
        JobStatus toCancel;
        synchronized (mJobs) {
            //【见小节4.3.1】
            toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
        }
        if (toCancel != null) {
            cancelJobImpl(toCancel);
        }
    }
    
    public void cancelJobsForUid(int uid) {
        List<JobStatus> jobsForUid;
        synchronized (mJobs) {
            //【见小节4.3.2】
            jobsForUid = mJobs.getJobsByUid(uid);
        }
        for (int i=0; i<jobsForUid.size(); i++) {
            JobStatus toRemove = jobsForUid.get(i);
            //【见小节4.4】
            cancelJobImpl(toRemove);
        }
    }
    ...
}

由上可知:

  • cancel(pid):调用JSS.cancelJob(uid, jobId)
  • cancelAll(): 调用JSS.cancelJobsForUid(uid)

以上两个方法,最终都会调用cancelJobImpl来取消任务的执行。

4.3.1 getJobByUidAndJobId

[-> JobStore.java]

public JobStatus getJobByUidAndJobId(int uid, int jobId) {
    Iterator<JobStatus> it = mJobSet.iterator();
    while (it.hasNext()) {
        JobStatus ts = it.next();
        if (ts.getUid() == uid && ts.getJobId() == jobId) {
            return ts;
        }
    }
    return null;
}

从mJobSet中查找指定uid和jobid的job;

4.3.2 getJobsByUid

[-> JobStore.java]

public List<JobStatus> getJobsByUid(int uid) {
    List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
    Iterator<JobStatus> it = mJobSet.iterator();
    while (it.hasNext()) {
        JobStatus ts = it.next();
        if (ts.getUid() == uid) {
            matchingJobs.add(ts);
        }
    }
    return matchingJobs;
}

遍历mJobSet中查找所有uid相同的jobs

4.4 JSS.cancelJobImpl

private void cancelJobImpl(JobStatus cancelled) {
    stopTrackingJob(cancelled); //【见小节4.5】
    synchronized (mJobs) {
        mPendingJobs.remove(cancelled);
        //【见小节4.6】
        stopJobOnServiceContextLocked(cancelled);
    }
}

4.5 JSS.stopTrackingJob

private boolean stopTrackingJob(JobStatus jobStatus) {
    boolean removed;
    boolean rocking;
    synchronized (mJobs) {
        removed = mJobs.remove(jobStatus);
        rocking = mReadyToRock;
    }
    if (removed && rocking) {
        for (int i=0; i<mControllers.size(); i++) {
            StateController controller = mControllers.get(i);
            //获取StateController的具体实现子类停止执行
            controller.maybeStopTrackingJob(jobStatus);
        }
    }
    return removed;
}

此处会依次调用前面注册的5个StateController来执行maybeStopTrackingJob。

4.6 JSS.stopJobOnServiceContextLocked

private boolean stopJobOnServiceContextLocked(JobStatus job) {
    for (int i=0; i<mActiveServices.size(); i++) {
        JobServiceContext jsc = mActiveServices.get(i);
        final JobStatus executing = jsc.getRunningJob();
        if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
            //找到匹配的正在执行任务,则取消该任务【见小节4.6.1】
            jsc.cancelExecutingJob();
            return true;
        }
    }
    return false;
}

4.6.1 JSC.cancelExecutingJob

[-> JobServiceContext.java]

void cancelExecutingJob() {
    //【见小节4.6.2】
    mCallbackHandler.obtainMessage(MSG_CANCEL).sendToTarget();
}

向运行在system_server主线程的JobServiceHandler发送MSG_CANCEL消息,接收到该消息,则执行handleCancelH();

4.6.2 JSC.handleCancelH

[-> JobServiceContext.java]

private void handleCancelH() {
    if (mRunningJob == null) {
        return;
    }
    switch (mVerb) {
        case VERB_BINDING:
        case VERB_STARTING:
            mCancelled.set(true);
            break;
        case VERB_EXECUTING:
            if (hasMessages(MSG_CALLBACK)) {
                //当client已调用jobFinished,则忽略本次取消操作
                return;
            }
            sendStopMessageH(); //【见小节4.6.3】
            break;
        case VERB_STOPPING:
            break;
        default:
            break;
    }
}

4.6.3 JSC.sendStopMessageH

private void sendStopMessageH() {
    removeOpTimeOut();
    if (mVerb != VERB_EXECUTING) {
        //停止还没有启动的job
        closeAndCleanupJobH(false /* reschedule */);
        return;
    }
    try {
        mVerb = VERB_STOPPING;
        scheduleOpTimeOut();
        //【见小节4.6.4】
        service.stopJob(mParams);
    } catch (RemoteException e) {
        closeAndCleanupJobH(false /* reschedule */);
    }
}

此处的service是由【小节3.11.1】所赋值,是指app端IJobService的代理类。经过binder call 回到app进程。

4.6.4 JobService.stopJob

[-> JobService.java]

public abstract class JobService extends Service {
    IJobService mBinder = new IJobService.Stub() {
        public void startJob(JobParameters jobParams) {
            ...
        }
        public void stopJob(JobParameters jobParams) {
            ensureHandler();
            //向主线程的Handler发送停止任务的消息【见小节4.6.5】
            Message m = Message.obtain(mHandler, MSG_STOP_JOB, jobParams);
            m.sendToTarget();
        }
    };
    
    ...
}

4.6.5 JS.JobHandler

[-> JobService.java ::JobHandler]

class JobHandler extends Handler {
    ...
    public void handleMessage(Message msg) {
        final JobParameters params = (JobParameters) msg.obj;
        switch (msg.what) {
            case MSG_EXECUTE_JOB:...
            case MSG_STOP_JOB:
                boolean ret = JobService.this.onStopJob(params);
                ackStopMessage(params, ret);
                break;
            case MSG_JOB_FINISHED:...
            default: break;
        }
    }
}  

回到主线程,调用onStopJob()方法。

四. 总结

JobScheduler启动调用schedule(),结束则调用cancel(int jobId)或cancelAll(),整个JobScheduler过程涉及不少记录job的对象,关系如下:

job

JobSchedulerService通过成员遍历mJobs指向JobStore对象;JobStore的mJobSet记录着所有的JobStatus对象; JobStatus通过job指向JobInfo对象; JobInfo对象里面记录着jobId, 组件名以及各种触发scheduler的限制条件信息.

再来看看整个jobscheduler的执行过程:点击查看大图

job_scheduler_sequence

上图整个过程涉及两次跨进程的调用, 第一次是从app进程进入system_server进程的JobSchedulerStub, 采用IJobScheduler接口. 第二次则是JobScheduler通过bindService方式启动之后, 再回到system_server进程,然后调用startJob(),这是通过IJobService接口, 这是oneway的方式,意味着不会等待对方完成便会结束.

当然在JobScheduler过程中前面介绍的5个StateController很重要,会根据时机来触发JobSchedulerService执行相应的满足条件的任务.

最终会回调目标应用中的JobService的onStartJob()方法, 可见该方法运行在app进程的主线程, 那么当存在耗时操作时则必须要采用异步方式, 让耗时操作交给子线程去执行,这样就不会阻塞app的UI线程.

另外,cancalAll()小心有坑,因为该方法的功能是取消该uid下的所有jobs,也就是说当存在多个app通过shareUid的方式,那么在其中任意一个app执行cancalAll(),则会把所有同一uid下的app中的jobs都cancel掉,这个应该是Google设计的缺陷,一定要谨慎处理。

理解AlarmManager机制

$
0
0

一. 概述

上一篇文章理解JobScheduler机制, 介绍了根据一定条件而触发的任务可以采用JobScheduler. 那么对于只是定时的任务, 而非考虑网络/时间之类的条件,也可以直接采用AlarmManager来完成.

AlarmManager的用法

PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_JOB_EXPIRED), 0);
AlarmManager alarmManager=(AlarmManager)getSystemService(Service.ALARM_SERVICE); 
alarmManager.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), pi);  

对于alarmManager关于alarm的类型, 以及时间到达后可以选择发送广播, 启动Activity或许启动服务等自由组合.

二. AlarmManager服务启动

2.1 startOtherServices

[-> SystemServer.java]

private void startOtherServices() {
  ...
  mSystemServiceManager.startService(AlarmManagerService.class);
  ...
}

AlarmManagerService的初始化比JobScheduler更早。

2.2 AlarmManagerService

[-> AlarmManagerService.java]

public AlarmManagerService(Context context) {
    super(context);
    mConstants = new Constants(mHandler);
}

此处AlarmHandler mHandler = new AlarmHandler(),该Handler运行在system_server的主线程。

2.2.1 创建Constants

[-> AlarmManagerService.java ::Constants]

private final class Constants extends ContentObserver {
    public Constants(Handler handler) {
        super(handler);
        updateAllowWhileIdleMinTimeLocked();
        updateAllowWhileIdleWhitelistDurationLocked();
    }
    
    public void updateAllowWhileIdleMinTimeLocked() {
        mAllowWhileIdleMinTime = mPendingIdleUntil != null
                ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME;
    }

    public void updateAllowWhileIdleWhitelistDurationLocked() {
        if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
            mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
            BroadcastOptions opts = BroadcastOptions.makeBasic();
            //设置为10s
            opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
            mIdleOptions = opts.toBundle();
        }
    }
    ...
}

当系统处于idle状态,则alarm最小时间间隔为9min;当处于非idle则最小时间间隔为5s.

2.3 ALMS.onStart

[-> AlarmManagerService.java]

public void onStart() {
    mNativeData = init(); //【2.4】
    mNextWakeup = mNextNonWakeup = 0;

    //由于重启后内核并没有保存时区信息,则必须将当前时区设置到内核;若时区改变则会发送相应
    setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));

    PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
    //TIME_TICK广播
    mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
            new Intent(Intent.ACTION_TIME_TICK).addFlags(
                    Intent.FLAG_RECEIVER_REGISTERED_ONLY
                    | Intent.FLAG_RECEIVER_FOREGROUND), 0,
                    UserHandle.ALL);
    //DATE_CHANGED广播
    Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
    intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
            
    //【见小节2.5】
    mClockReceiver = new ClockReceiver();
    //首次调度一次,后面每分钟执行一次【见小节2.6】
    mClockReceiver.scheduleTimeTickEvent();
    //日期改变的广播,流程同上
    mClockReceiver.scheduleDateChangedEvent();
    
    //用于监听亮屏/灭屏广播
    mInteractiveStateReceiver = new InteractiveStateReceiver();
    //用于监听package移除/重启,sdcard不可用的广播
    mUninstallReceiver = new UninstallReceiver();
    
    if (mNativeData != 0) {
        //创建"AlarmManager"【见小节2.8】
        AlarmThread waitThread = new AlarmThread();
        waitThread.start();
    } 
    //发布alarm服务
    publishBinderService(Context.ALARM_SERVICE, mService);
}

该方法主要功能:

  1. 将时区信息设置到内核;其中时区属性TIMEZONE_PROPERTY = “persist.sys.timezone”
  2. 创建ClockReceiver广播接收者,用于监听TIME_TICK和DATE_CHANGED广播;
  3. 创建InteractiveStateReceiver,用于监听亮屏/灭屏广播;
  4. 创建UninstallReceiver,用于监听package移除/重启,sdcard不可用的广播;
  5. 创建线程”AlarmManager”;
  6. 发布alarm服务信息;

2.4 init

[-> com_android_server_AlarmManagerService.cpp]

static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
{
    jlong ret = init_alarm_driver(); //【2.4.1】
    if (ret) {
        return ret;
    }
    return init_timerfd(); //【2.4.2】
}

2.4.1 init_alarm_driver

static jlong init_alarm_driver()
{
    int fd = open("/dev/alarm", O_RDWR);
    //创建Alarm驱动对象
    AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
    return reinterpret_cast<jlong>(ret);
}

打开节点/dev/alarm,并创建Alarm驱动对象。

2.4.2 init_timerfd

static jlong init_timerfd()
{
    int epollfd;
    int fds[N_ANDROID_TIMERFDS];

    epollfd = epoll_create(N_ANDROID_TIMERFDS);
    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
        fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
        
    }

    //创建AlarmImplTimerFd对象
    AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());
    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
        epoll_event event;
        event.events = EPOLLIN | EPOLLWAKEUP;
        event.data.u32 = i;

        int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
        ...
    }

    struct itimerspec spec;
    memset(&spec, 0, sizeof(spec));

    int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
            TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
    ...

    return reinterpret_cast<jlong>(ret);
}

此处android_alarm_to_clockid数组如下:

android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
    CLOCK_REALTIME_ALARM,
    CLOCK_REALTIME,
    CLOCK_BOOTTIME_ALARM,
    CLOCK_BOOTTIME,
    CLOCK_MONOTONIC,
    CLOCK_REALTIME,
};

此处创建AlarmImplTimerFd

2.5 创建ClockReceiver

[-> AlarmManagerService.java ::ClockReceiver]

class ClockReceiver extends BroadcastReceiver {
    public ClockReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_TIME_TICK);
        filter.addAction(Intent.ACTION_DATE_CHANGED);
        getContext().registerReceiver(this, filter);
    }
    ...
}

注册用于监听TIME_TICK和DATE_CHANGED的广播。

2.6 scheduleTimeTickEvent

[-> AlarmManagerService.java ::ClockReceiver]

public void scheduleTimeTickEvent() {
    final long currentTime = System.currentTimeMillis();
    final long nextTime = 60000 * ((currentTime / 60000) + 1);
    //距离下一分钟的时间戳
    final long tickEventDelay = nextTime - currentTime;

    final WorkSource workSource = null
    //【见小节2.7】
    setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
            0, mTimeTickSender, AlarmManager.FLAG_STANDALONE, workSource, null,
            Process.myUid());
}

2.7 ALMS.setImpl

[-> AlarmManagerService.java]

void setImpl(int type, long triggerAtTime, long windowLength, long interval,
         PendingIntent operation, int flags, WorkSource workSource,
         AlarmManager.AlarmClockInfo alarmClock, int callingUid) {
      ...
     final long nowElapsed = SystemClock.elapsedRealtime();
     //获取闹钟触发的时间点
     final long nominalTrigger = convertToElapsed(triggerAtTime, type);
     final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
     //保证alarm时间至少是在5s之后发生
     final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;

     final long maxElapsed;
     if (windowLength == AlarmManager.WINDOW_EXACT) {
         maxElapsed = triggerElapsed;
     } else if (windowLength < 0) {
         maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
         windowLength = maxElapsed - triggerElapsed;
     } else {
         maxElapsed = triggerElapsed + windowLength;
     }

     synchronized (mLock) {
         //【见小节2.7.1】
         setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
                 interval, operation, flags, true, workSource, alarmClock, callingUid);
     }
 }

2.7.1 ALMS.setImplLocked

private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
        long maxWhen, long interval, PendingIntent operation, int flags,
        boolean doValidate, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
        int uid) {
    //创建Alarm对象
    Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
            operation, workSource, flags, alarmClock, uid);
    removeLocked(operation);
    //【见小节2.7.2】
    setImplLocked(a, false, doValidate);
}

2.7.2 ALMS.setImplLocked

private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
    if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
        if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
            a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
        }
        //增加模糊事件,让alarm比实际预期事件更早的执行
        final long nowElapsed = SystemClock.elapsedRealtime();
        final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
        if (fuzz > 0) {
            if (mRandom == null) {
                mRandom = new Random();
            }
            //创建随机模糊时间
            final int delta = mRandom.nextInt(fuzz);
            a.whenElapsed -= delta;
            a.when = a.maxWhenElapsed = a.whenElapsed;
        }

    } else if (mPendingIdleUntil != null) {
        if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
                | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
                | AlarmManager.FLAG_WAKE_FROM_IDLE))
                == 0) {
            mPendingWhileIdleAlarms.add(a);
            return;
        }
    }

    int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
            ? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
    if (whichBatch < 0) {
        //TIME_TICK是独立的,不与其他alarm一起批处理
        Batch batch = new Batch(a);
        addBatchLocked(mAlarmBatches, batch);
    } else {
        ...
    }
    ...

    boolean needRebatch = false;

    if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
        mPendingIdleUntil = a;
        mConstants.updateAllowWhileIdleMinTimeLocked();
        needRebatch = true;
    } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
        if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
            mNextWakeFromIdle = a;
            if (mPendingIdleUntil != null) {
                needRebatch = true;
            }
        }
    }

    if (!rebatching) {
        if (needRebatch) {
            //需要对所有alarm重新执行批处理
            rebatchAllAlarmsLocked(false);
        }

        rescheduleKernelAlarmsLocked();
        //重新计算下一个alarm
        updateNextAlarmClockLocked();
    }
}

再来看看”AlarmManager”线程的工作过程.

2.8 AlarmThread

[-> AlarmManagerService.java ::AlarmThread]

private class AlarmThread extends Thread
{
    public AlarmThread()
    {
        super("AlarmManager");
    }
    
    public void run()
    {
        ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
        while (true)
        {
            //[见小节2.8.1]
            int result = waitForAlarm(mNativeData);
            triggerList.clear();

            final long nowRTC = System.currentTimeMillis();
            final long nowELAPSED = SystemClock.elapsedRealtime();

            if ((result & TIME_CHANGED_MASK) != 0) {
                ...
            }

            if (result != TIME_CHANGED_MASK) {
                synchronized (mLock) {
                    boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
                    if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
                        if (mPendingNonWakeupAlarms.size() == 0) {
                            mStartCurrentDelayTime = nowELAPSED;
                            mNextNonWakeupDeliveryTime = nowELAPSED
                                    + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
                        }
                        mPendingNonWakeupAlarms.addAll(triggerList);
                        mNumDelayedAlarms += triggerList.size();
                        rescheduleKernelAlarmsLocked();
                        updateNextAlarmClockLocked();
                    } else {
                        rescheduleKernelAlarmsLocked();
                        updateNextAlarmClockLocked();
                        if (mPendingNonWakeupAlarms.size() > 0) {
                            calculateDeliveryPriorities(mPendingNonWakeupAlarms);
                            triggerList.addAll(mPendingNonWakeupAlarms);
                            Collections.sort(triggerList, mAlarmDispatchComparator);
                            final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
                            mTotalDelayTime += thisDelayTime;
                            if (mMaxDelayTime < thisDelayTime) {
                                mMaxDelayTime = thisDelayTime;
                            }
                            mPendingNonWakeupAlarms.clear();
                        }
                        //分发Alarm事件.[见小节4.1]
                        deliverAlarmsLocked(triggerList, nowELAPSED);
                    }
                }
            }
        }
    }
}

2.8.1 waitForAlarm

[-> com_android_server_AlarmManagerService.cpp]

int AlarmImplTimerFd::waitForAlarm()
{
    epoll_event events[N_ANDROID_TIMERFDS];

    int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
    if (nevents < 0) {
        return nevents;
    }

    int result = 0;
    for (int i = 0; i < nevents; i++) {
        uint32_t alarm_idx = events[i].data.u32;
        uint64_t unused;
        ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
        if (err < 0) {
            if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
                result |= ANDROID_ALARM_TIME_CHANGE_MASK;
            } else {
                return err;
            }
        } else {
            result |= (1 << alarm_idx);
        }
    }

    return result;
}

三. alarm使用

//【见小节3.1】
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_JOB_EXPIRED), 0);
AlarmManager alarmManager=(AlarmManager)getSystemService(Service.ALARM_SERVICE); 
//[见小节3.3]
alarmManager.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), pi);  

alarm使用过程会使用到PendingIntent,先来简单介绍下PendingIntent.

3.1 PendingIntent

常见PendingIntent常见的几个静态方法如下:

PendingIntent.getActivity
PendingIntent.getService
PendingIntent.getBroadcastAsUser

以上3个方法最终都会调用到AMS.getIntentSender,主要的不同在于第一个参数TYPE.

3.1.1 getBroadcastAsUser

[-> PendingIntent.java]

public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
        Intent intent, int flags, UserHandle userHandle) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        intent.prepareToLeaveProcess();
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                ActivityManager.INTENT_SENDER_BROADCAST, packageName,
                null, null, requestCode, new Intent[] { intent },
                resolvedType != null ? new String[] { resolvedType } : null,
                flags, null, userHandle.getIdentifier());
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

getIntentSender()获取的是PendingIntentRecord对象, 而该对象继承于IIntentSender.Stub, 经过binder call回来, 所以此处target是指PendingIntentRecord对象的代理端, 即为PendingIntent.mTarget.

3.1.2 getActivity

public static PendingIntent getActivityAsUser(Context context, int requestCode,
        Intent intent, int flags, Bundle options, UserHandle user) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        //[见小节3.1.4]
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
                null, null, requestCode, new Intent[] { intent },
                resolvedType != null ? new String[] { resolvedType } : null,
                flags, options, user.getIdentifier());
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

3.1.3 getService

public static PendingIntent getService(Context context, int requestCode,
         Intent intent,  int flags) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        intent.prepareToLeaveProcess();
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                ActivityManager.INTENT_SENDER_SERVICE, packageName,
                null, null, requestCode, new Intent[] { intent },
                resolvedType != null ? new String[] { resolvedType } : null,
                flags, null, UserHandle.myUserId());
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

3.1.4 AMS.getIntentSender

public IIntentSender getIntentSender(int type,
        String packageName, IBinder token, String resultWho,
        int requestCode, Intent[] intents, String[] resolvedTypes,
        int flags, Bundle options, int userId) {
    //重新拷贝一次intent对象内容
    if (intents != null) {
        for (int i=0; i<intents.length; i++) {
            Intent intent = intents[i];
            if (intent != null) {
                intents[i] = new Intent(intent);
            }
        }
    }
    ...
    
    synchronized(this) {
        int callingUid = Binder.getCallingUid();
        int origUserId = userId;
        userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
                type == ActivityManager.INTENT_SENDER_BROADCAST,
                ALLOW_NON_FULL, "getIntentSender", null);
        if (origUserId == UserHandle.USER_CURRENT) {
            userId = UserHandle.USER_CURRENT;
        }
        //【见小节3.1.5】
        return getIntentSenderLocked(type, packageName, callingUid, userId,
              token, resultWho, requestCode, intents, resolvedTypes, flags, options);
    }
}

3.1.5 AMS.getIntentSenderLocked

IIntentSender getIntentSenderLocked(int type, String packageName,
        int callingUid, int userId, IBinder token, String resultWho,
        int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
        Bundle options) {
    ActivityRecord activity = null;
    ...
    //创建Key对象
    PendingIntentRecord.Key key = new PendingIntentRecord.Key(
            type, packageName, activity, resultWho,
            requestCode, intents, resolvedTypes, flags, options, userId);
    WeakReference<PendingIntentRecord> ref;
    ref = mIntentSenderRecords.get(key);
    PendingIntentRecord rec = ref != null ? ref.get() : null;
    if (rec != null) {
        if (!cancelCurrent) {
            if (updateCurrent) {
                if (rec.key.requestIntent != null) {
                    rec.key.requestIntent.replaceExtras(intents != null ?
                            intents[intents.length - 1] : null);
                }
                if (intents != null) {
                    intents[intents.length-1] = rec.key.requestIntent;
                    rec.key.allIntents = intents;
                    rec.key.allResolvedTypes = resolvedTypes;
                } else {
                    rec.key.allIntents = null;
                    rec.key.allResolvedTypes = null;
                }
            }
            return rec;
        }
        rec.canceled = true;
        mIntentSenderRecords.remove(key);
    }
    if (noCreate) {
        return rec;
    }
    //创建PendingIntentRecord对象
    rec = new PendingIntentRecord(this, key, callingUid);
    mIntentSenderRecords.put(key, rec.ref);
    ...
    return rec;
}

3.2 AlarmManager

registerService(Context.ALARM_SERVICE, AlarmManager.class,
        new CachedServiceFetcher<AlarmManager>() {

    public AlarmManager createService(ContextImpl ctx) {
        IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
        IAlarmManager service = IAlarmManager.Stub.asInterface(b);
        return new AlarmManager(service, ctx);
    }});

由此可知,getSystemService(Service.ALARM_SERVICE)获取的是AlarmManager对象,再来看看其创建过程。

[-> AlarmManager.java]

AlarmManager(IAlarmManager service, Context ctx) {
    mService = service; //ALMS的binder代理端
    mPackageName = ctx.getPackageName();
    mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion;
    mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT);
    mMainThreadHandler = new Handler(ctx.getMainLooper());
}

此处mMainThreadHandler是运行在app进程的主线程。

3.3 AlarmManager.set

[-> AlarmManager.java]

public void set(int type, long triggerAtMillis, PendingIntent operation) {
    //[见小节3.4]
    setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null,
        null, null, null);
}

3.4 AlarmManager.setImpl

[-> AlarmManager.java]

private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
        int flags, PendingIntent operation, final OnAlarmListener listener, String listenerTag,
        Handler targetHandler, WorkSource workSource, AlarmClockInfo alarmClock) {
    ListenerWrapper recipientWrapper = null;
    if (listener != null) {
        synchronized (AlarmManager.class) {
            if (sWrappers == null) {
                sWrappers = new ArrayMap<OnAlarmListener, ListenerWrapper>();
            }

            recipientWrapper = sWrappers.get(listener);
            if (recipientWrapper == null) {
                recipientWrapper = new ListenerWrapper(listener);
                sWrappers.put(listener, recipientWrapper);
            }
        }
        //当没有设置handler对象时,则采用当前进程的主线程handler
        final Handler handler = (targetHandler != null) ? targetHandler : mMainThreadHandler;
        recipientWrapper.setHandler(handler);
    }
    //【见小节2.7】
    mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags,
            operation, recipientWrapper, listenerTag, workSource, alarmClock);
}

注意: 此处targetHandler这个是在Android N上才有的逻辑. 此处mService是指远程IAlarmManager的代理类, 服务类位于ALMS的成员变量mService = new IAlarmManager.Stub()。 可见,接下来程序运行到system_server进程。

四. alarm分发流程

由[]小节2.8] 可知当alarm时间触发时则执行deliverAlarmsLocked(), 接下来,从该方法说起.

4.1 deliverAlarmsLocked

[-> AlarmManagerService.java]

void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
    mLastAlarmDeliveryTime = nowELAPSED;
    for (int i=0; i<triggerList.size(); i++) {
        Alarm alarm = triggerList.get(i);
        final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
        try {
            ...
            //[见小节4.2]
            mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
        } catch (RuntimeException e) {
        }
    }
}

4.2 ALMS.deliverLocked

[-> AlarmManagerService.java]

public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
    if (alarm.operation != null) {
        //执行PendingIntent操作[见小节4.3]
        alarm.operation.send(getContext(), 0,
                mBackgroundIntent.putExtra(
                    Intent.EXTRA_ALARM_COUNT, alarm.count),
                    mDeliveryTracker, mHandler, null,
                    allowWhileIdle ? mIdleOptions : null);
    } else {
       //[见小节4.4]
       alarm.listener.doAlarm(this);
       // 5s的超时时长 
       mHandler.sendMessageDelayed(
               mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
                       alarm.listener.asBinder()),
               mConstants.LISTENER_TIMEOUT);
    }
    //alarm正在触发
    final InFlight inflight = new InFlight(AlarmManagerService.this,
            alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
            alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
    mInFlight.add(inflight);
    mBroadcastRefCount++;
    qcNsrmExt.addTriggeredUid((alarm.operation != null) ?
                            alarm.operation.getCreatorUid() :
                            alarm.uid);
    ...
}

4.3 PendingIntent.send

[-> PendingIntent.java]

public void send(Context context, int code, @Nullable Intent intent,
        @Nullable OnFinished onFinished, @Nullable Handler handler,
        @Nullable String requiredPermission, @Nullable Bundle options)
        throws CanceledException {
    try {
        String resolvedType = intent != null ?
                intent.resolveTypeIfNeeded(context.getContentResolver())
                : null;
        int res = mTarget.send(code, intent, resolvedType,
                onFinished != null
                        ? new FinishedDispatcher(this, onFinished, handler)
                        : null,
                requiredPermission, options);
        ...
    } catch (RemoteException e) {
        throw new CanceledException(e);
    }
}

由小节3.1, 可知mTarget代表的是远端PendingIntentRecord对象. 可知接下来进入到system_server的如下方法.

4.3.1 pendingIntentRecord.send

[-> pendingIntentRecord.java]

public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
        String requiredPermission, Bundle options) throws TransactionTooLargeException {
    return sendInner(code, intent, resolvedType, finishedReceiver,
            requiredPermission, null, null, 0, 0, 0, options, null);
}

4.3.2 sendInner

[-> pendingIntentRecord.java]

int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
        String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
        int flagsMask, int flagsValues, Bundle options, IActivityContainer container)
        throws TransactionTooLargeException {
    synchronized(owner) {
            ...
            final long origId = Binder.clearCallingIdentity();

            boolean sendFinish = finishedReceiver != null;
            int userId = key.userId;
            if (userId == UserHandle.USER_CURRENT) {
                userId = owner.getCurrentUserIdLocked();
            }
            switch (key.type) {
                case ActivityManager.INTENT_SENDER_ACTIVITY:
                    ...
                    if (key.allIntents != null && key.allIntents.length > 1) {
                        Intent[] allIntents = new Intent[key.allIntents.length];
                        String[] allResolvedTypes = new String[key.allIntents.length];
                        System.arraycopy(key.allIntents, 0, allIntents, 0,
                                key.allIntents.length);
                        if (key.allResolvedTypes != null) {
                            System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
                                    key.allResolvedTypes.length);
                        }
                        allIntents[allIntents.length-1] = finalIntent;
                        allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
                        //核心方法
                        owner.startActivitiesInPackage(uid, key.packageName, allIntents,
                                allResolvedTypes, resultTo, options, userId);
                    } else {
                        owner.startActivityInPackage(uid, key.packageName, finalIntent,
                                resolvedType, resultTo, resultWho, requestCode, 0,
                                options, userId, container, null);
                    }
                    break;
                case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
                    if (key.activity.task.stack != null) {
                        //核心方法
                        key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
                                key.who, key.requestCode, code, finalIntent);
                    }
                    break;
                case ActivityManager.INTENT_SENDER_BROADCAST:
                    //核心方法
                    int sent = owner.broadcastIntentInPackage(key.packageName, uid,
                            finalIntent, resolvedType, finishedReceiver, code, null, null,
                            requiredPermission, options, (finishedReceiver != null),
                            false, userId);
                    if (sent == ActivityManager.BROADCAST_SUCCESS) {
                        sendFinish = false;
                    }

                    break;
                case ActivityManager.INTENT_SENDER_SERVICE:
                    //核心方法
                    owner.startServiceInPackage(uid, finalIntent,
                            resolvedType, key.packageName, userId);
                    break;
            }

            if (sendFinish) {
                finishedReceiver.performReceive(new Intent(finalIntent), 0,
                        null, null, false, false, key.userId);
            }
            Binder.restoreCallingIdentity(origId);
            return 0;
        }
    }
    return ActivityManager.START_CANCELED;
}

可见,

  • INTENT_SENDER_ACTIVITY: 则执行startActivitiesInPackage
  • INTENT_SENDER_ACTIVITY_RESULT: 则执行sendActivityResultLocked
  • INTENT_SENDER_SERVICE: 则执行startServiceInPackage
  • INTENT_SENDER_BROADCAST: 则执行broadcastIntentInPackage
    • 当广播发送不成功, 且需要发送广播,则直接执行startServiceInPackage

再回到小节4.2 deliverLocked,可知当没有指定PendingIntent时,则会回调listener的doAlarm()过程. 由[小节3.4]创建的ListenerWrapper对象.

4.4 ListenerWrapper.doAlarm

[-> AlarmManager.java ::ListenerWrapper]

 final class ListenerWrapper extends IAlarmListener.Stub implements Runnable {
     final OnAlarmListener mListener;
     Handler mHandler;
     IAlarmCompleteListener mCompletion;

     public ListenerWrapper(OnAlarmListener listener) {
         mListener = listener;
     }

     //执行alarm操作[见小节4.4.1]
     public void doAlarm(IAlarmCompleteListener alarmManager) {
         mCompletion = alarmManager;
         mHandler.post(this);
     }
 }

默认情况下mHandler是指设置闹钟setImpl方法所在进程的主线程, 当然也可以指定Handler线程. 对于前面JobSchedulerService中用到的TimeController 则是在system_server进程设置的闹钟, 那么接下来post到了system_server的主线程.

4.4.1 ListenerWrapper.run

final class ListenerWrapper extends IAlarmListener.Stub implements Runnable {
    
    public void run() {
        //从wrapper的缓存中移除该listener, 由于服务端已经认为它不存在
        synchronized (AlarmManager.class) {
            if (sWrappers != null) {
                sWrappers.remove(mListener);
            }
        }

        
        try {
            //分发目标监听者的onAlarm[4.4.2]
            mListener.onAlarm();
        } finally {
            mCompletion.alarmComplete(this);
        }
    }
}

这里以TimeController为例, 可知接下来,便会进入mNextDelayExpiredListener.onAlarm()的过程

4.4.2 TimeController

[-> TimeController.java]

private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, int uid) {
    alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
    mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
    //将mNextDelayExpiredListener设置到alarm的回调过程
    updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener,
            mNextDelayExpiredElapsedMillis, uid);
}

private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener,
        long alarmTimeElapsed, int uid) {
    ensureAlarmServiceLocked();
    if (alarmTimeElapsed == Long.MAX_VALUE) {
        ...
    } else {
        mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTimeElapsed,
                AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, new WorkSource(uid));
    }
}


private final OnAlarmListener mNextDelayExpiredListener = new OnAlarmListener() {
    @Override
    public void onAlarm() {
        checkExpiredDelaysAndResetAlarm();
    }
};

此处没有指定handler, 则onAlarm回调方法默认运行在system_server的主线程.

五 总结

  1. AlarmManagerService.mHandler 也是运行在system_server的主线程;
  2. 防止alarm频繁发起,则最小时间间隔5s;

设置闹钟有3种类型:

set(int type,long startTime,PendingIntent pi),//设置一次闹钟
setRepeating(int type,long startTime,long intervalTime,PendingIntent pi),//设置重复闹钟
setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi),//设置重复闹钟,但不准确

Type有4种类型:

类型是否能唤醒系统是否包含休眠时间
RTC_WAKEUP
RTC
ELAPSED_REALTIME_WAKEUP
ELAPSED_REALTIME

未完, 待续…

理解AlarmManager机制

$
0
0

一. 概述

上一篇文章理解JobScheduler机制, 介绍了根据一定条件而触发的任务可以采用JobScheduler. 那么对于只是定时的任务, 而非考虑网络/时间之类的条件,也可以直接采用AlarmManager来完成.

AlarmManager的用法

PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_JOB_EXPIRED), 0);
AlarmManager alarmManager=(AlarmManager)getSystemService(Service.ALARM_SERVICE); 
alarmManager.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), pi);  

对于alarmManager关于alarm的类型, 以及时间到达后可以选择发送广播, 启动Activity或许启动服务等自由组合.

二. AlarmManager服务启动

2.1 startOtherServices

[-> SystemServer.java]

private void startOtherServices() {
  ...
  mSystemServiceManager.startService(AlarmManagerService.class);
  ...
}

AlarmManagerService的初始化比JobScheduler更早。

2.2 AlarmManagerService

[-> AlarmManagerService.java]

public AlarmManagerService(Context context) {
    super(context);
    mConstants = new Constants(mHandler);
}

此处AlarmHandler mHandler = new AlarmHandler(),该Handler运行在system_server的主线程。

2.2.1 创建Constants

[-> AlarmManagerService.java ::Constants]

private final class Constants extends ContentObserver {
    public Constants(Handler handler) {
        super(handler);
        updateAllowWhileIdleMinTimeLocked();
        updateAllowWhileIdleWhitelistDurationLocked();
    }
    
    public void updateAllowWhileIdleMinTimeLocked() {
        mAllowWhileIdleMinTime = mPendingIdleUntil != null
                ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME;
    }

    public void updateAllowWhileIdleWhitelistDurationLocked() {
        if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
            mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
            BroadcastOptions opts = BroadcastOptions.makeBasic();
            //设置为10s
            opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
            mIdleOptions = opts.toBundle();
        }
    }
    ...
}

当系统处于idle状态,则alarm最小时间间隔为9min;当处于非idle则最小时间间隔为5s.

2.3 ALMS.onStart

[-> AlarmManagerService.java]

public void onStart() {
    mNativeData = init(); //【2.4】
    mNextWakeup = mNextNonWakeup = 0;

    //由于重启后内核并没有保存时区信息,则必须将当前时区设置到内核;若时区改变则会发送相应
    setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));

    PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
    mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
    //TIME_TICK广播
    mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
            new Intent(Intent.ACTION_TIME_TICK).addFlags(
                    Intent.FLAG_RECEIVER_REGISTERED_ONLY
                    | Intent.FLAG_RECEIVER_FOREGROUND), 0,
                    UserHandle.ALL);
    //DATE_CHANGED广播
    Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
    intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
            
    //【见小节2.5】
    mClockReceiver = new ClockReceiver();
    //首次调度一次,后面每分钟执行一次【见小节2.6】
    mClockReceiver.scheduleTimeTickEvent();
    //日期改变的广播,流程同上
    mClockReceiver.scheduleDateChangedEvent();
    
    //用于监听亮屏/灭屏广播
    mInteractiveStateReceiver = new InteractiveStateReceiver();
    //用于监听package移除/重启,sdcard不可用的广播
    mUninstallReceiver = new UninstallReceiver();
    
    if (mNativeData != 0) {
        //创建"AlarmManager"【见小节2.8】
        AlarmThread waitThread = new AlarmThread();
        waitThread.start();
    } 
    //发布alarm服务
    publishBinderService(Context.ALARM_SERVICE, mService);
}

该方法主要功能:

  1. 将时区信息设置到内核;其中时区属性TIMEZONE_PROPERTY = “persist.sys.timezone”
  2. 创建ClockReceiver广播接收者,用于监听TIME_TICK和DATE_CHANGED广播;
  3. 创建InteractiveStateReceiver,用于监听亮屏/灭屏广播;
  4. 创建UninstallReceiver,用于监听package移除/重启,sdcard不可用的广播;
  5. 创建线程”AlarmManager”;
  6. 发布alarm服务信息;

2.4 init

[-> com_android_server_AlarmManagerService.cpp]

static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
{
    jlong ret = init_alarm_driver(); //【2.4.1】
    if (ret) {
        return ret;
    }
    return init_timerfd(); //【2.4.2】
}

2.4.1 init_alarm_driver

static jlong init_alarm_driver()
{
    int fd = open("/dev/alarm", O_RDWR);
    //创建Alarm驱动对象
    AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
    return reinterpret_cast<jlong>(ret);
}

打开节点/dev/alarm,并创建Alarm驱动对象。

2.4.2 init_timerfd

static jlong init_timerfd()
{
    int epollfd;
    int fds[N_ANDROID_TIMERFDS];

    epollfd = epoll_create(N_ANDROID_TIMERFDS);
    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
        fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
        
    }

    //创建AlarmImplTimerFd对象
    AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());
    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
        epoll_event event;
        event.events = EPOLLIN | EPOLLWAKEUP;
        event.data.u32 = i;

        int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
        ...
    }

    struct itimerspec spec;
    memset(&spec, 0, sizeof(spec));

    int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
            TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
    ...

    return reinterpret_cast<jlong>(ret);
}

此处android_alarm_to_clockid数组如下:

android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
    CLOCK_REALTIME_ALARM,
    CLOCK_REALTIME,
    CLOCK_BOOTTIME_ALARM,
    CLOCK_BOOTTIME,
    CLOCK_MONOTONIC,
    CLOCK_REALTIME,
};

此处创建AlarmImplTimerFd

2.5 创建ClockReceiver

[-> AlarmManagerService.java ::ClockReceiver]

class ClockReceiver extends BroadcastReceiver {
    public ClockReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_TIME_TICK);
        filter.addAction(Intent.ACTION_DATE_CHANGED);
        getContext().registerReceiver(this, filter);
    }
    ...
}

注册用于监听TIME_TICK和DATE_CHANGED的广播。

2.6 scheduleTimeTickEvent

[-> AlarmManagerService.java ::ClockReceiver]

public void scheduleTimeTickEvent() {
    final long currentTime = System.currentTimeMillis();
    final long nextTime = 60000 * ((currentTime / 60000) + 1);
    //距离下一分钟的时间戳
    final long tickEventDelay = nextTime - currentTime;

    final WorkSource workSource = null
    //【见小节2.7】
    setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
            0, mTimeTickSender, AlarmManager.FLAG_STANDALONE, workSource, null,
            Process.myUid());
}

2.7 ALMS.setImpl

[-> AlarmManagerService.java]

void setImpl(int type, long triggerAtTime, long windowLength, long interval,
         PendingIntent operation, int flags, WorkSource workSource,
         AlarmManager.AlarmClockInfo alarmClock, int callingUid) {
      ...
     final long nowElapsed = SystemClock.elapsedRealtime();
     //获取闹钟触发的时间点
     final long nominalTrigger = convertToElapsed(triggerAtTime, type);
     final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
     //保证alarm时间至少是在5s之后发生
     final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;

     final long maxElapsed;
     if (windowLength == AlarmManager.WINDOW_EXACT) {
         maxElapsed = triggerElapsed;
     } else if (windowLength < 0) {
         maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
         windowLength = maxElapsed - triggerElapsed;
     } else {
         maxElapsed = triggerElapsed + windowLength;
     }

     synchronized (mLock) {
         //【见小节2.7.1】
         setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
                 interval, operation, flags, true, workSource, alarmClock, callingUid);
     }
 }

2.7.1 ALMS.setImplLocked

private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
        long maxWhen, long interval, PendingIntent operation, int flags,
        boolean doValidate, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
        int uid) {
    //创建Alarm对象
    Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
            operation, workSource, flags, alarmClock, uid);
    removeLocked(operation);
    //【见小节2.7.2】
    setImplLocked(a, false, doValidate);
}

2.7.2 ALMS.setImplLocked

private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
    if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
        if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
            a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
        }
        //增加模糊事件,让alarm比实际预期事件更早的执行
        final long nowElapsed = SystemClock.elapsedRealtime();
        final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
        if (fuzz > 0) {
            if (mRandom == null) {
                mRandom = new Random();
            }
            //创建随机模糊时间
            final int delta = mRandom.nextInt(fuzz);
            a.whenElapsed -= delta;
            a.when = a.maxWhenElapsed = a.whenElapsed;
        }

    } else if (mPendingIdleUntil != null) {
        if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
                | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
                | AlarmManager.FLAG_WAKE_FROM_IDLE))
                == 0) {
            mPendingWhileIdleAlarms.add(a);
            return;
        }
    }

    int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
            ? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
    if (whichBatch < 0) {
        //TIME_TICK是独立的,不与其他alarm一起批处理
        Batch batch = new Batch(a);
        addBatchLocked(mAlarmBatches, batch);
    } else {
        ...
    }
    ...

    boolean needRebatch = false;

    if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
        mPendingIdleUntil = a;
        mConstants.updateAllowWhileIdleMinTimeLocked();
        needRebatch = true;
    } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
        if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
            mNextWakeFromIdle = a;
            if (mPendingIdleUntil != null) {
                needRebatch = true;
            }
        }
    }

    if (!rebatching) {
        if (needRebatch) {
            //需要对所有alarm重新执行批处理
            rebatchAllAlarmsLocked(false);
        }

        rescheduleKernelAlarmsLocked();
        //重新计算下一个alarm
        updateNextAlarmClockLocked();
    }
}

再来看看”AlarmManager”线程的工作过程.

2.8 AlarmThread

[-> AlarmManagerService.java ::AlarmThread]

private class AlarmThread extends Thread
{
    public AlarmThread()
    {
        super("AlarmManager");
    }
    
    public void run()
    {
        ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
        while (true)
        {
            //[见小节2.8.1]
            int result = waitForAlarm(mNativeData);
            triggerList.clear();

            final long nowRTC = System.currentTimeMillis();
            final long nowELAPSED = SystemClock.elapsedRealtime();

            if ((result & TIME_CHANGED_MASK) != 0) {
                ...
            }

            if (result != TIME_CHANGED_MASK) {
                synchronized (mLock) {
                    boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
                    if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
                        if (mPendingNonWakeupAlarms.size() == 0) {
                            mStartCurrentDelayTime = nowELAPSED;
                            mNextNonWakeupDeliveryTime = nowELAPSED
                                    + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
                        }
                        mPendingNonWakeupAlarms.addAll(triggerList);
                        mNumDelayedAlarms += triggerList.size();
                        rescheduleKernelAlarmsLocked();
                        updateNextAlarmClockLocked();
                    } else {
                        rescheduleKernelAlarmsLocked();
                        updateNextAlarmClockLocked();
                        if (mPendingNonWakeupAlarms.size() > 0) {
                            calculateDeliveryPriorities(mPendingNonWakeupAlarms);
                            triggerList.addAll(mPendingNonWakeupAlarms);
                            Collections.sort(triggerList, mAlarmDispatchComparator);
                            final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
                            mTotalDelayTime += thisDelayTime;
                            if (mMaxDelayTime < thisDelayTime) {
                                mMaxDelayTime = thisDelayTime;
                            }
                            mPendingNonWakeupAlarms.clear();
                        }
                        //分发Alarm事件.[见小节4.1]
                        deliverAlarmsLocked(triggerList, nowELAPSED);
                    }
                }
            }
        }
    }
}

2.8.1 waitForAlarm

[-> com_android_server_AlarmManagerService.cpp]

int AlarmImplTimerFd::waitForAlarm()
{
    epoll_event events[N_ANDROID_TIMERFDS];

    int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
    if (nevents < 0) {
        return nevents;
    }

    int result = 0;
    for (int i = 0; i < nevents; i++) {
        uint32_t alarm_idx = events[i].data.u32;
        uint64_t unused;
        ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
        if (err < 0) {
            if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
                result |= ANDROID_ALARM_TIME_CHANGE_MASK;
            } else {
                return err;
            }
        } else {
            result |= (1 << alarm_idx);
        }
    }

    return result;
}

三. alarm使用

//【见小节3.1】
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_JOB_EXPIRED), 0);
AlarmManager alarmManager=(AlarmManager)getSystemService(Service.ALARM_SERVICE); 
//[见小节3.3]
alarmManager.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), pi);  

alarm使用过程会使用到PendingIntent,先来简单介绍下PendingIntent.

3.1 PendingIntent

常见PendingIntent常见的几个静态方法如下:

PendingIntent.getActivity
PendingIntent.getService
PendingIntent.getBroadcastAsUser

以上3个方法最终都会调用到AMS.getIntentSender,主要的不同在于第一个参数TYPE.

3.1.1 getBroadcastAsUser

[-> PendingIntent.java]

public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
        Intent intent, int flags, UserHandle userHandle) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        intent.prepareToLeaveProcess();
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                ActivityManager.INTENT_SENDER_BROADCAST, packageName,
                null, null, requestCode, new Intent[] { intent },
                resolvedType != null ? new String[] { resolvedType } : null,
                flags, null, userHandle.getIdentifier());
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

getIntentSender()获取的是PendingIntentRecord对象, 而该对象继承于IIntentSender.Stub, 经过binder call回来, 所以此处target是指PendingIntentRecord对象的代理端, 即为PendingIntent.mTarget.

3.1.2 getActivity

public static PendingIntent getActivityAsUser(Context context, int requestCode,
        Intent intent, int flags, Bundle options, UserHandle user) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        //[见小节3.1.4]
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
                null, null, requestCode, new Intent[] { intent },
                resolvedType != null ? new String[] { resolvedType } : null,
                flags, options, user.getIdentifier());
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

3.1.3 getService

public static PendingIntent getService(Context context, int requestCode,
         Intent intent,  int flags) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
            context.getContentResolver()) : null;
    try {
        intent.prepareToLeaveProcess();
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
                ActivityManager.INTENT_SENDER_SERVICE, packageName,
                null, null, requestCode, new Intent[] { intent },
                resolvedType != null ? new String[] { resolvedType } : null,
                flags, null, UserHandle.myUserId());
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}

3.1.4 AMS.getIntentSender

public IIntentSender getIntentSender(int type,
        String packageName, IBinder token, String resultWho,
        int requestCode, Intent[] intents, String[] resolvedTypes,
        int flags, Bundle options, int userId) {
    //重新拷贝一次intent对象内容
    if (intents != null) {
        for (int i=0; i<intents.length; i++) {
            Intent intent = intents[i];
            if (intent != null) {
                intents[i] = new Intent(intent);
            }
        }
    }
    ...
    
    synchronized(this) {
        int callingUid = Binder.getCallingUid();
        int origUserId = userId;
        userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
                type == ActivityManager.INTENT_SENDER_BROADCAST,
                ALLOW_NON_FULL, "getIntentSender", null);
        if (origUserId == UserHandle.USER_CURRENT) {
            userId = UserHandle.USER_CURRENT;
        }
        //【见小节3.1.5】
        return getIntentSenderLocked(type, packageName, callingUid, userId,
              token, resultWho, requestCode, intents, resolvedTypes, flags, options);
    }
}

3.1.5 AMS.getIntentSenderLocked

IIntentSender getIntentSenderLocked(int type, String packageName,
        int callingUid, int userId, IBinder token, String resultWho,
        int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
        Bundle options) {
    ActivityRecord activity = null;
    ...
    //创建Key对象
    PendingIntentRecord.Key key = new PendingIntentRecord.Key(
            type, packageName, activity, resultWho,
            requestCode, intents, resolvedTypes, flags, options, userId);
    WeakReference<PendingIntentRecord> ref;
    ref = mIntentSenderRecords.get(key);
    PendingIntentRecord rec = ref != null ? ref.get() : null;
    if (rec != null) {
        if (!cancelCurrent) {
            if (updateCurrent) {
                if (rec.key.requestIntent != null) {
                    rec.key.requestIntent.replaceExtras(intents != null ?
                            intents[intents.length - 1] : null);
                }
                if (intents != null) {
                    intents[intents.length-1] = rec.key.requestIntent;
                    rec.key.allIntents = intents;
                    rec.key.allResolvedTypes = resolvedTypes;
                } else {
                    rec.key.allIntents = null;
                    rec.key.allResolvedTypes = null;
                }
            }
            return rec;
        }
        rec.canceled = true;
        mIntentSenderRecords.remove(key);
    }
    if (noCreate) {
        return rec;
    }
    //创建PendingIntentRecord对象
    rec = new PendingIntentRecord(this, key, callingUid);
    mIntentSenderRecords.put(key, rec.ref);
    ...
    return rec;
}

3.2 AlarmManager

registerService(Context.ALARM_SERVICE, AlarmManager.class,
        new CachedServiceFetcher<AlarmManager>() {

    public AlarmManager createService(ContextImpl ctx) {
        IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
        IAlarmManager service = IAlarmManager.Stub.asInterface(b);
        return new AlarmManager(service, ctx);
    }});

由此可知,getSystemService(Service.ALARM_SERVICE)获取的是AlarmManager对象,再来看看其创建过程。

[-> AlarmManager.java]

AlarmManager(IAlarmManager service, Context ctx) {
    mService = service; //ALMS的binder代理端
    mPackageName = ctx.getPackageName();
    mTargetSdkVersion = ctx.getApplicationInfo().targetSdkVersion;
    mAlwaysExact = (mTargetSdkVersion < Build.VERSION_CODES.KITKAT);
    mMainThreadHandler = new Handler(ctx.getMainLooper());
}

此处mMainThreadHandler是运行在app进程的主线程。

3.3 AlarmManager.set

[-> AlarmManager.java]

public void set(int type, long triggerAtMillis, PendingIntent operation) {
    //[见小节3.4]
    setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null,
        null, null, null);
}

3.4 AlarmManager.setImpl

[-> AlarmManager.java]

private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
        int flags, PendingIntent operation, final OnAlarmListener listener, String listenerTag,
        Handler targetHandler, WorkSource workSource, AlarmClockInfo alarmClock) {
    ListenerWrapper recipientWrapper = null;
    if (listener != null) {
        synchronized (AlarmManager.class) {
            if (sWrappers == null) {
                sWrappers = new ArrayMap<OnAlarmListener, ListenerWrapper>();
            }

            recipientWrapper = sWrappers.get(listener);
            if (recipientWrapper == null) {
                recipientWrapper = new ListenerWrapper(listener);
                sWrappers.put(listener, recipientWrapper);
            }
        }
        //当没有设置handler对象时,则采用当前进程的主线程handler
        final Handler handler = (targetHandler != null) ? targetHandler : mMainThreadHandler;
        recipientWrapper.setHandler(handler);
    }
    //【见小节2.7】
    mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags,
            operation, recipientWrapper, listenerTag, workSource, alarmClock);
}

注意: 此处targetHandler这个是在Android N上才有的逻辑. 此处mService是指远程IAlarmManager的代理类, 服务类位于ALMS的成员变量mService = new IAlarmManager.Stub()。 可见,接下来程序运行到system_server进程。

四. alarm分发流程

由[]小节2.8] 可知当alarm时间触发时则执行deliverAlarmsLocked(), 接下来,从该方法说起.

4.1 deliverAlarmsLocked

[-> AlarmManagerService.java]

void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
    mLastAlarmDeliveryTime = nowELAPSED;
    for (int i=0; i<triggerList.size(); i++) {
        Alarm alarm = triggerList.get(i);
        final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
        try {
            ...
            //[见小节4.2]
            mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
        } catch (RuntimeException e) {
        }
    }
}

4.2 ALMS.deliverLocked

[-> AlarmManagerService.java]

public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
    if (alarm.operation != null) {
        //执行PendingIntent操作[见小节4.3]
        alarm.operation.send(getContext(), 0,
                mBackgroundIntent.putExtra(
                    Intent.EXTRA_ALARM_COUNT, alarm.count),
                    mDeliveryTracker, mHandler, null,
                    allowWhileIdle ? mIdleOptions : null);
    } else {
       //[见小节4.4]
       alarm.listener.doAlarm(this);
       // 5s的超时时长 
       mHandler.sendMessageDelayed(
               mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
                       alarm.listener.asBinder()),
               mConstants.LISTENER_TIMEOUT);
    }
    //alarm正在触发
    final InFlight inflight = new InFlight(AlarmManagerService.this,
            alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
            alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
    mInFlight.add(inflight);
    mBroadcastRefCount++;
    qcNsrmExt.addTriggeredUid((alarm.operation != null) ?
                            alarm.operation.getCreatorUid() :
                            alarm.uid);
    ...
}

4.3 PendingIntent.send

[-> PendingIntent.java]

public void send(Context context, int code, @Nullable Intent intent,
        @Nullable OnFinished onFinished, @Nullable Handler handler,
        @Nullable String requiredPermission, @Nullable Bundle options)
        throws CanceledException {
    try {
        String resolvedType = intent != null ?
                intent.resolveTypeIfNeeded(context.getContentResolver())
                : null;
        int res = mTarget.send(code, intent, resolvedType,
                onFinished != null
                        ? new FinishedDispatcher(this, onFinished, handler)
                        : null,
                requiredPermission, options);
        ...
    } catch (RemoteException e) {
        throw new CanceledException(e);
    }
}

由小节3.1, 可知mTarget代表的是远端PendingIntentRecord对象. 可知接下来进入到system_server的如下方法.

4.3.1 pendingIntentRecord.send

[-> pendingIntentRecord.java]

public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
        String requiredPermission, Bundle options) throws TransactionTooLargeException {
    return sendInner(code, intent, resolvedType, finishedReceiver,
            requiredPermission, null, null, 0, 0, 0, options, null);
}

4.3.2 sendInner

[-> pendingIntentRecord.java]

int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
        String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
        int flagsMask, int flagsValues, Bundle options, IActivityContainer container)
        throws TransactionTooLargeException {
    synchronized(owner) {
            ...
            final long origId = Binder.clearCallingIdentity();

            boolean sendFinish = finishedReceiver != null;
            int userId = key.userId;
            if (userId == UserHandle.USER_CURRENT) {
                userId = owner.getCurrentUserIdLocked();
            }
            switch (key.type) {
                case ActivityManager.INTENT_SENDER_ACTIVITY:
                    ...
                    if (key.allIntents != null && key.allIntents.length > 1) {
                        Intent[] allIntents = new Intent[key.allIntents.length];
                        String[] allResolvedTypes = new String[key.allIntents.length];
                        System.arraycopy(key.allIntents, 0, allIntents, 0,
                                key.allIntents.length);
                        if (key.allResolvedTypes != null) {
                            System.arraycopy(key.allResolvedTypes, 0, allResolvedTypes, 0,
                                    key.allResolvedTypes.length);
                        }
                        allIntents[allIntents.length-1] = finalIntent;
                        allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
                        //核心方法
                        owner.startActivitiesInPackage(uid, key.packageName, allIntents,
                                allResolvedTypes, resultTo, options, userId);
                    } else {
                        owner.startActivityInPackage(uid, key.packageName, finalIntent,
                                resolvedType, resultTo, resultWho, requestCode, 0,
                                options, userId, container, null);
                    }
                    break;
                case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
                    if (key.activity.task.stack != null) {
                        //核心方法
                        key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
                                key.who, key.requestCode, code, finalIntent);
                    }
                    break;
                case ActivityManager.INTENT_SENDER_BROADCAST:
                    //核心方法
                    int sent = owner.broadcastIntentInPackage(key.packageName, uid,
                            finalIntent, resolvedType, finishedReceiver, code, null, null,
                            requiredPermission, options, (finishedReceiver != null),
                            false, userId);
                    if (sent == ActivityManager.BROADCAST_SUCCESS) {
                        sendFinish = false;
                    }

                    break;
                case ActivityManager.INTENT_SENDER_SERVICE:
                    //核心方法
                    owner.startServiceInPackage(uid, finalIntent,
                            resolvedType, key.packageName, userId);
                    break;
            }

            if (sendFinish) {
                finishedReceiver.performReceive(new Intent(finalIntent), 0,
                        null, null, false, false, key.userId);
            }
            Binder.restoreCallingIdentity(origId);
            return 0;
        }
    }
    return ActivityManager.START_CANCELED;
}

可见,

  • INTENT_SENDER_ACTIVITY: 则执行startActivitiesInPackage
  • INTENT_SENDER_ACTIVITY_RESULT: 则执行sendActivityResultLocked
  • INTENT_SENDER_SERVICE: 则执行startServiceInPackage
  • INTENT_SENDER_BROADCAST: 则执行broadcastIntentInPackage
    • 当广播发送不成功, 且需要发送广播,则直接执行startServiceInPackage

再回到小节4.2 deliverLocked,可知当没有指定PendingIntent时,则会回调listener的doAlarm()过程. 由[小节3.4]创建的ListenerWrapper对象.

4.4 ListenerWrapper.doAlarm

[-> AlarmManager.java ::ListenerWrapper]

 final class ListenerWrapper extends IAlarmListener.Stub implements Runnable {
     final OnAlarmListener mListener;
     Handler mHandler;
     IAlarmCompleteListener mCompletion;

     public ListenerWrapper(OnAlarmListener listener) {
         mListener = listener;
     }

     //执行alarm操作[见小节4.4.1]
     public void doAlarm(IAlarmCompleteListener alarmManager) {
         mCompletion = alarmManager;
         mHandler.post(this);
     }
 }

默认情况下mHandler是指设置闹钟setImpl方法所在进程的主线程, 当然也可以指定Handler线程. 对于前面JobSchedulerService中用到的TimeController 则是在system_server进程设置的闹钟, 那么接下来post到了system_server的主线程.

4.4.1 ListenerWrapper.run

final class ListenerWrapper extends IAlarmListener.Stub implements Runnable {
    
    public void run() {
        //从wrapper的缓存中移除该listener, 由于服务端已经认为它不存在
        synchronized (AlarmManager.class) {
            if (sWrappers != null) {
                sWrappers.remove(mListener);
            }
        }

        
        try {
            //分发目标监听者的onAlarm[4.4.2]
            mListener.onAlarm();
        } finally {
            mCompletion.alarmComplete(this);
        }
    }
}

这里以TimeController为例, 可知接下来,便会进入mNextDelayExpiredListener.onAlarm()的过程

4.4.2 TimeController

[-> TimeController.java]

private void setDelayExpiredAlarmLocked(long alarmTimeElapsedMillis, int uid) {
    alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
    mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
    //将mNextDelayExpiredListener设置到alarm的回调过程
    updateAlarmWithListenerLocked(DELAY_TAG, mNextDelayExpiredListener,
            mNextDelayExpiredElapsedMillis, uid);
}

private void updateAlarmWithListenerLocked(String tag, OnAlarmListener listener,
        long alarmTimeElapsed, int uid) {
    ensureAlarmServiceLocked();
    if (alarmTimeElapsed == Long.MAX_VALUE) {
        ...
    } else {
        mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTimeElapsed,
                AlarmManager.WINDOW_HEURISTIC, 0, tag, listener, null, new WorkSource(uid));
    }
}


private final OnAlarmListener mNextDelayExpiredListener = new OnAlarmListener() {
    @Override
    public void onAlarm() {
        checkExpiredDelaysAndResetAlarm();
    }
};

此处没有指定handler, 则onAlarm回调方法默认运行在system_server的主线程.

五 总结

  1. AlarmManagerService.mHandler 也是运行在system_server的主线程;
  2. 防止alarm频繁发起,则最小时间间隔5s;

设置闹钟有3种类型:

set(int type,long startTime,PendingIntent pi),//设置一次闹钟
setRepeating(int type,long startTime,long intervalTime,PendingIntent pi),//设置重复闹钟
setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi),//设置重复闹钟,但不准确

Type有4种类型:

类型是否能唤醒系统是否包含休眠时间
RTC_WAKEUP
RTC
ELAPSED_REALTIME_WAKEUP
ELAPSED_REALTIME

未完, 待续…

Android类加载器ClassLoader

$
0
0

本文讲述的Android系统体系架构,说一说ClassLoader加载过程

一. 概述

Android从5.0开始就采用art虚拟机, 该虚拟机有些类似Java虚拟机, 程序运行过程也需要通过ClassLoader 将目标类加载到内存.

传统Jvm主要是通过读取class字节码来加载, 而art则是从dex字节码来读取. 这是一种更为优化的方案, 可以将多个.class文件合并成一个classes.dex文件. 下面直接来看看ClassLoader的关系

1.1 架构图

Android中最为常用的便是PathClassLoader.

二. ClassLoader构造函数

2.1 PathClassLoader

public class PathClassLoader extends BaseDexClassLoader {

    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }

    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}

PathClassLoader比较简单, 继承于BaseDexClassLoader. 封装了一下构造函数, 默认 optimizedDirectory=null.

2.2 DexClassLoader

public class DexClassLoader extends BaseDexClassLoader {

    public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}

DexClassLoader也同样,只是简单地封装了BaseDexClassLoader对象,并没有覆写父类的任何方法.

2.3 BaseDexClassLoader

public class BaseDexClassLoader extends ClassLoader {
    private final DexPathList pathList;

    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
        String libraryPath, ClassLoader parent) {
        super(parent);
        //[见小节2.3.1]
        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
    }
}

BaseDexClassLoader构造函数, 有一个非常重要的过程, 那就是初始化DexPathList对象.

另外该构造函数的参数说明:

  • dexPath: 包含目标类或资源的apk/jar列表;当有多个路径则采用:分割;
  • optimizedDirectory: 优化后的dex文件存在的目录, 可以为null;
  • libraryPath: native库所在路径列表;当有多个路径则采用:分割;
  • ClassLoader:父类的类加载器.

2.3.1 DexPathList

public DexPathList(ClassLoader definingContext, String dexPath,
        String libraryPath, File optimizedDirectory) {
    ...
    this.definingContext = definingContext;

    ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
    //记录所有的dexFile文件
    this.dexElements = makePathElements(splitDexPath(dexPath), optimizedDirectory, suppressedExceptions);

    //app目录的native库
    this.nativeLibraryDirectories = splitPaths(libraryPath, false);
    //系统目录的native库
    this.systemNativeLibraryDirectories = splitPaths(System.getProperty("java.library.path"), true);
    List<File> allNativeLibraryDirectories = new ArrayList<>(nativeLibraryDirectories);
    allNativeLibraryDirectories.addAll(systemNativeLibraryDirectories);
    //记录所有的Native动态库
    this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null,
                                                      suppressedExceptions);
    ...
}

DexPathList初始化过程,主要功能是收集以下两个变量信息:

  1. dexElements: 记录所有的dexFile文件
  2. nativeLibraryPathElements: 记录所有的Native动态库, 包括app目录的native库和系统目录的native库.

2.4 BootClassLoader

class BootClassLoader extends ClassLoader {
    private static BootClassLoader instance;

    public static synchronized BootClassLoader getInstance() {
        if (instance == null) {
            instance = new BootClassLoader();
        }

        return instance;
    }

    public BootClassLoader() {
        super(null, true);
    } }

以上所有的ClassLoader都直接或间接着继承于抽象类ClassLoader.

2.5 ClassLoader

public abstract class ClassLoader {
    private ClassLoader parent;

    protected ClassLoader() {
        //[见小节2.5.1]
        this(getSystemClassLoader(), false);
    }

    protected ClassLoader(ClassLoader parentLoader) {
        this(parentLoader, false);
    }

    ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
        if (parentLoader == null && !nullAllowed) {
            //父类的类加载器为空,则抛出异常
            throw new NullPointerException("parentLoader == null && !nullAllowed");
        }
        parent = parentLoader;
    }
}

2.5.1 SystemClassLoader

public abstract class ClassLoader {

    static private class SystemClassLoader {
        public static ClassLoader loader = ClassLoader.createSystemClassLoader();
    }

    public static ClassLoader getSystemClassLoader() {
        return SystemClassLoader.loader;
    }

    private static ClassLoader createSystemClassLoader() {
        String classPath = System.getProperty("java.class.path", ".");
        return new PathClassLoader(classPath, BootClassLoader.getInstance());
    }
}

2.6 小节

  • PathClassLoader: 主要用于系统和app的类加载器,其中optimizedDirectory为null, 则采用默认目录/data/dalvik-cache/
  • DexClassLoader: 可以从包含classes.dex的jar/apk中加载类的类加载器, 可用于执行动态加载,但必须是app私有可写目录来缓存odx文件. 能够加载系统没有安装的apk/jar
  • BaseDexClassLoader: 比较基础的类加载器, PathClassLoader和DexClassLoader都只是在构造函数上对其简单封装而已.
  • BootClassLoader: 作为父类的类构造器.

三. loadClass

此处以PathClassLoader为例来说明

3.1 loadClass

public abstract class ClassLoader {

    public Class<?> loadClass(String className) throws ClassNotFoundException {
        return loadClass(className, false);
    }

    protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
        Class<?> clazz = findLoadedClass(className);

        if (clazz == null) {
            ClassNotFoundException suppressed = null;
            try {
                clazz = parent.loadClass(className, false);
            } catch (ClassNotFoundException e) {
                suppressed = e;
            }

            if (clazz == null) {
                try {
                    //[见小节3.2]
                    clazz = findClass(className);
                } catch (ClassNotFoundException e) {
                    e.addSuppressed(suppressed);
                    throw e;
                }
            }
        }

        return clazz;
    }
}

3.2 findClass

public class BaseDexClassLoader extends ClassLoader {
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
        //[见小节3.3]
        Class c = pathList.findClass(name, suppressedExceptions);
        ...
        return c;
    }
}

3.3 DexPathList.findClass

final class DexPathList {
    public Class findClass(String name, List<Throwable> suppressed) {
        for (Element element : dexElements) {
            DexFile dex = element.dexFile;

            if (dex != null) {
                //[见小节3.4]
                Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
                if (clazz != null) {
                    return clazz;
                }
            }
        }
        if (dexElementsSuppressedExceptions != null) {
            suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
        }
        return null;
    }
}

3.4 DexFile.loadClassBinaryName

public final class DexFile {

    public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) {
        return defineClass(name, loader, mCookie, suppressed);
    }

    private static Class defineClass(String name, ClassLoader loader, Object cookie,
                                     List<Throwable> suppressed) {
        Class result = null;
        try {
            result = defineClassNative(name, loader, cookie);
        } catch (NoClassDefFoundError e) {
            if (suppressed != null) {
                suppressed.add(e);
            }
        } catch (ClassNotFoundException e) {
            if (suppressed != null) {
                suppressed.add(e);
            }
        }
        return result;
    }
}

defineClassNative()这是native方法, 进入如下方法.

3.5 defineClassNative

[-> dalvik_system_DexFile.cc]

static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, jobject javaLoader,
                                        jobject cookie) {
  std::unique_ptr<std::vector<const DexFile*>> dex_files = ConvertJavaArrayToNative(env, cookie);
  if (dex_files.get() == nullptr) {
    return nullptr; //dex文件为空, 则直接返回
  }

  ScopedUtfChars class_name(env, javaName);
  if (class_name.c_str() == nullptr) {
    return nullptr; //类名为空, 则直接返回
  }

  const std::string descriptor(DotToDescriptor(class_name.c_str()));
  const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str())); //将类名转换为hash码
  for (auto& dex_file : *dex_files) {
    const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor.c_str(), hash);
    if (dex_class_def != nullptr) {
      ScopedObjectAccess soa(env);
      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
      class_linker->RegisterDexFile(*dex_file);
      StackHandleScope<1> hs(soa.Self());
      Handle<mirror::ClassLoader> class_loader(
          hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
      //获取目标类
      mirror::Class* result = class_linker->DefineClass(soa.Self(), descriptor.c_str(), hash,
                                                        class_loader, *dex_file, *dex_class_def);
      if (result != nullptr) {
        // 找到目标对象
        return soa.AddLocalReference<jclass>(result);
      }
    }
  }
  return nullptr; //没有找到目标类
}

loadLibrary动态库加载过程分析

$
0
0

本文讲述的Android系统体系架构, 分析动态库的加载过程.

libcore/luni/src/main/java/java/lang/System.java
libcore/luni/src/main/java/java/lang/Runtime.java
libcore/luni/src/main/native/java_lang_System.cpp
bionic/linker/linker.cpp
art/runtime/native/java_lang_Runtime.cc
art/runtime/java_vm_ext.cc

一. 概述

动态库操作,所需要的头文件的#include, 最为核心的方法如下:

void *dlopen(const char * pathname,int mode);  //打开动态库  
void *dlsym(void *handle,const char *name);  //获取动态库对象地址  
char *dlerror(vid);   //错误检测  
int dlclose(void * handle); //关闭动态库  

而对于android上层的Java代码来说,都封装好了, 只需要一行代码就即可完成动态库的加载过程,如下:

System.loadLibrary("gityuan_jni");

接下来,解析这行代码背后的故事.

二. 动态库加载过程

2.1 System.loadLibrary

[-> System.java]

public static void loadLibrary(String libName) {
    Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
}

此处getCallingClassLoader返回的是调用者所定义的ClassLoader.

2.2 Runtime.loadLibrary

[-> Runtime.java]

void loadLibrary(String libraryName, ClassLoader loader) {
    if (loader != null) {
        //[见小节2.4]
        String filename = loader.findLibrary(libraryName);
        if (filename == null) {
            throw new UnsatisfiedLinkError(...);
        }
        //成功执行完doLoad,则返回.[见小节2.5]
        String error = doLoad(filename, loader);
        if (error != null) {
            throw new UnsatisfiedLinkError(error);
        }
        return;
    }
    //当loader为空的情况下执行[见2.3]
    String filename = System.mapLibraryName(libraryName);
    List<String> candidates = new ArrayList<String>();
    String lastError = null;

    //此处的mLibPaths取值 [见小节三]
    for (String directory : mLibPaths) {
        String candidate = directory + filename;
        candidates.add(candidate);

        if (IoUtils.canOpenReadOnly(candidate)) {
            String error = doLoad(candidate, loader);
            if (error == null) {
                return; //成功执行完doLoad,则返回.
            }
            lastError = error;
        }
    }

    if (lastError != null) {
        throw new UnsatisfiedLinkError(lastError);
    }
    throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
}

加载库的两条路径,如下:

  • 当loader不为空时, 通过该loader来findLibrary()查看目标库所在路径;
  • 当loader为空时, 则从默认目录mLibPaths下来查找是否存在该动态库;

不管loader是否为空, 找到目标库所在路径后,都会调用doLoad来真正用于加载动态库.

2.3 loader为空的情况

[-> System.java]

public static String mapLibraryName(String nickname) {
    if (nickname == null) {
        throw new NullPointerException("nickname == null");
    }
    return "lib" + nickname + ".so";
}

该方法的功能是将xxx动态库的名字转换为libxxx.so. 比如前面传递过来的nickname为gityuan_jni, 经过该方法处理后返回的名字为libgityuan_jni.so.

mLibPaths取值分两种情况:

  • 对于64系统,则为/system/lib64和/vendor/lib64;
  • 对于32系统,则为/system/lib和/vendor/lib.

假设此处为64位系统, 则会去查找/system/lib64/libgityuan_jni.so或/vendor/lib64/libgityuan_jni.so库是否存在.

绝大多数的动态库都在/system/lib64或/system/lib路径下.通过canOpenReadOnly方法来判定目标动态库是否存在, 找到则直接返回,否则抛出UnsatisfiedLinkError异常.

2.4 loader不为空的情况

ClassLoader一般来说都是PathClassLoader, 这就不再解释. 从该对象的findLibrary说起. 由于PathClassLoader继承于 BaseDexClassLoader对象, 并且没有覆写该方法, 故调用其父类所对应的方法.

2.4.1 findLibrary

[-> BaseDexClassLoader.java]

public class BaseDexClassLoader extends ClassLoader {
    private final DexPathList pathList;

    public BaseDexClassLoader(String dexPath, File optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(parent);
        //dexPath一般是指apk所在路径
        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
    }

    public String findLibrary(String name) {
        return pathList.findLibrary(name); //[见小节2.4.3]
    }
}

2.4.2 DexPathList

[-> DexPathList.java]

public DexPathList(ClassLoader definingContext, String dexPath,
        String libraryPath, File optimizedDirectory) {
    ...
    this.definingContext = definingContext;

    ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
    //记录所有的dexFile文件
    this.dexElements = makePathElements(splitDexPath(dexPath), optimizedDirectory, suppressedExceptions);

    //app目录的native库
    this.nativeLibraryDirectories = splitPaths(libraryPath, false);
    //系统目录的native库
    this.systemNativeLibraryDirectories = splitPaths(System.getProperty("java.library.path"), true);
    List<File> allNativeLibraryDirectories = new ArrayList<>(nativeLibraryDirectories);
    allNativeLibraryDirectories.addAll(systemNativeLibraryDirectories);
    //记录所有的Native动态库
    this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null,
                                                      suppressedExceptions);
    ...
}

DexPathList初始化过程,主要功能是收集以下两个变量信息:

  1. dexElements: 记录所有的dexFile文件
  2. nativeLibraryPathElements: 记录所有的Native动态库, 包括app目录的native库和系统目录的native库.

接下来便是从pathList中查询目标动态库.

2.4.3 findLibrary

[-> DexPathList.java]

public String findLibrary(String libraryName) {
    String fileName = System.mapLibraryName(libraryName);

    for (Element element : nativeLibraryPathElements) {
        //[见小节2.4.4]
        String path = element.findNativeLibrary(fileName);
        if (path != null) {
            return path;
        }
    }
    return null;
}

gityuan_jni同样也是经过mapLibraryName(), 处理后得到的名字为libgityuan_jni.so. 接下来,从所有的动态库nativeLibraryPathElements(包含两个系统路径)查询是否存在匹配的. 这里举例说明, 一般地会在以下两个路径查找(以64位为例):

  • /data/app/com.gityuan.blog-1/lib/arm64
  • /vendor/lib64
  • /system/lib64

2.4.4 findNativeLibrary

[-> DexPathList.java ::Element]

final class DexPathList {
    static class Element {

        public String findNativeLibrary(String name) {
            maybeInit();
            if (isDirectory) {
                String path = new File(dir, name).getPath();
                if (IoUtils.canOpenReadOnly(path)) {
                    return path;
                }
            } else if (zipFile != null) {
                String entryName = new File(dir, name).getPath();
                if (isZipEntryExistsAndStored(zipFile, entryName)) {
                  return zip.getPath() + zipSeparator + entryName;
                }
            }
            return null;
        }
    }
}

遍历查询,一旦找到则返回所找到的目标动态库. 接下来, 再回到[小节2.2]来看看动态库的加载doLoad:

2.5 Runtime.doLoad

[-> Runtime.java]

private String doLoad(String name, ClassLoader loader) {
    String ldLibraryPath = null;
    String dexPath = null;
    if (loader == null) {
        ldLibraryPath = System.getProperty("java.library.path");
    } else if (loader instanceof BaseDexClassLoader) {
        BaseDexClassLoader dexClassLoader = (BaseDexClassLoader) loader;
        ldLibraryPath = dexClassLoader.getLdLibraryPath();
    }
    synchronized (this) {
        //[见小节2.5.1]
        return nativeLoad(name, loader, ldLibraryPath);
    }
}

此处ldLibraryPath有两种情况:

  • 当loader为空, 则ldLibraryPath为系统目录下的Native库;
  • 当lodder不为空, 则ldLibraryPath为app目录下的Native库;

接下来, 继续看看nativeLoad.

2.5.1 nativeLoad

[-> java_lang_Runtime.cc]

static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, jobject javaLoader,
                                  jstring javaLdLibraryPathJstr) {
  ScopedUtfChars filename(env, javaFilename);
  if (filename.c_str() == nullptr) {
    return nullptr;
  }

  SetLdLibraryPath(env, javaLdLibraryPathJstr);

  std::string error_msg;
  {
    JavaVMExt* vm = Runtime::Current()->GetJavaVM();
    //[见小节2.5.2]
    bool success = vm->LoadNativeLibrary(env, filename.c_str(), javaLoader, &error_msg);
    if (success) {
      return nullptr;
    }
  }

  env->ExceptionClear();
  return env->NewStringUTF(error_msg.c_str());
}

nativeLoad方法经过jni,进入该方法执行.

2.5.2 LoadNativeLibrary

[-> java_vm_ext.cc]

bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, const std::string& path, jobject class_loader,
                                  std::string* error_msg) {
  error_msg->clear();

  SharedLibrary* library;
  Thread* self = Thread::Current();
  {
    MutexLock mu(self, *Locks::jni_libraries_lock_);
    library = libraries_->Get(path); //检查该动态库是否已加载
  }
  if (library != nullptr) {
    if (env->IsSameObject(library->GetClassLoader(), class_loader) == JNI_FALSE) {
      //不能加载同一个采用多个不同的ClassLoader
      return false;
    }
    ...
    return true;
  }

  const char* path_str = path.empty() ? nullptr : path.c_str();
  //通过dlopen打开动态共享库.该库不会立刻被卸载直到引用技术为空.
  void* handle = dlopen(path_str, RTLD_NOW);
  bool needs_native_bridge = false;
  if (handle == nullptr) {
    if (android::NativeBridgeIsSupported(path_str)) {
      handle = android::NativeBridgeLoadLibrary(path_str, RTLD_NOW);
      needs_native_bridge = true;
    }
  }

  if (handle == nullptr) {
    *error_msg = dlerror(); //打开失败
    VLOG(jni) << "dlopen(\""<< path << "\", RTLD_NOW) failed: "<< *error_msg;
    return false;
  }


  bool created_library = false;
  {
    std::unique_ptr<SharedLibrary> new_library(
        new SharedLibrary(env, self, path, handle, class_loader));
    MutexLock mu(self, *Locks::jni_libraries_lock_);
    library = libraries_->Get(path);
    if (library == nullptr) {
      library = new_library.release();
      //创建共享库,并添加到列表
      libraries_->Put(path, library);
      created_library = true;
    }
  }
  ...

  bool was_successful = false;
  void* sym;
  //查询JNI_OnLoad符号所对应的方法
  if (needs_native_bridge) {
    library->SetNeedsNativeBridge();
    sym = library->FindSymbolWithNativeBridge("JNI_OnLoad", nullptr);
  } else {
    sym = dlsym(handle, "JNI_OnLoad");
  }

  if (sym == nullptr) {
    was_successful = true;
  } else {
    //需要先覆盖当前ClassLoader.
    ScopedLocalRef<jobject> old_class_loader(env, env->NewLocalRef(self->GetClassLoaderOverride()));
    self->SetClassLoaderOverride(class_loader);

    typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
    JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
    // 真正调用JNI_OnLoad()方法的过程
    int version = (*jni_on_load)(this, nullptr);

    if (runtime_->GetTargetSdkVersion() != 0 && runtime_->GetTargetSdkVersion() <= 21) {
      fault_manager.EnsureArtActionInFrontOfSignalChain();
    }
    //执行完成后, 需要恢复到原来的ClassLoader
    self->SetClassLoaderOverride(old_class_loader.get());
    ...
  }

  library->SetResult(was_successful);
  return was_successful;
}

该过程简单总结:

  1. 检查该动态库是否已加载;
  2. 通过dlopen打开动态共享库;
  3. 创建SharedLibrary共享库,并添加到libraries_列表;
  4. 找到JNI_OnLoad符号所对应的方法, 并调用该方法.

三. mLibPaths初始化

mLibPaths的初始化过程, 要从libcore/luni/src/main/java/java/lang/System.java类的静态代码块初始化开始说起. 对于类的静态代码块,编译过程会将所有的静态代码块和静态成员变量的赋值过程都收集整合到clinit方法, 即类的初始化方法.如下:

public final class System {
    static {
        ...
        //[见小节3.1]
        unchangeableSystemProperties = initUnchangeableSystemProperties();
        systemProperties = createSystemProperties();
        addLegacyLocaleSystemProperties();
    }
}

3.1 initUnchangeableSystemProperties

[-> System.java]

private static Properties initUnchangeableSystemProperties() {
    VMRuntime runtime = VMRuntime.getRuntime();
    Properties p = new Properties();
    ...
    p.put("java.boot.class.path", runtime.bootClassPath());
    p.put("java.class.path", runtime.classPath());
    // [见小节3.2]
    parsePropertyAssignments(p, specialProperties());
    ...
    return p;
}

这个过程会将大量的key-value对保存到Properties对象, 这种重点看specialProperties

3.1.1 parsePropertyAssignments

[-> System.java]

private static void parsePropertyAssignments(Properties p, String[] assignments) {
    for (String assignment : assignments) {
        int split = assignment.indexOf('=');
        String key = assignment.substring(0, split);
        String value = assignment.substring(split + 1);
        p.put(key, value);
    }
}

将assignments数据解析后保存到Properties对象.

3.2 specialProperties

[-> java_lang_System.cpp]

static jobjectArray System_specialProperties(JNIEnv* env, jclass) {
    std::vector<std::string> properties;
    char path[PATH_MAX];
    ...

    const char* library_path = getenv("LD_LIBRARY_PATH");
    if (library_path == NULL) {
        // [见小节3.3]
        android_get_LD_LIBRARY_PATH(path, sizeof(path));
        library_path = path;
    }
    properties.push_back(std::string("java.library.path=") + library_path);
    return toStringArray(env, properties);
}

环境变量LD_LIBRARY_PATH为空, 可通过adb shell env命令来查看环境变量的值. 接下来进入android_get_LD_LIBRARY_PATH方法, 该方法调用do_android_get_LD_LIBRARY_PATH,见下文:

3.3 do_android_get_LD_LIBRARY_PATH

[-> linker.cpp]

void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
  //[见小节3.4]
  size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2;
  char* end = stpcpy(buffer, kDefaultLdPaths[0]);
  *end = ':';
  strcpy(end + 1, kDefaultLdPaths[1]);
}

可见赋值过程还得看kDefaultLdPaths数组.

3.4 kDefaultLdPaths

[-> linker.cpp]

static const char* const kDefaultLdPaths[] = {
#if defined(__LP64__)
  "/vendor/lib64",
  "/system/lib64",
#else
  "/vendor/lib",
  "/system/lib",
#endif
  nullptr
};

对于linux 64位操作系统则定义__LP64__宏, 可知mLibPaths取值分两种情况:

  • 对于64系统,则为/system/lib64和/vendor/lib64;
  • 对于32系统,则为/system/lib和/vendor/lib.

也可以通过System.getProperty(“java.library.path”)来获取该值.

理解Application初始化

$
0
0

一. 概述

system进程和app进程都运行着一个或多个app,每个app都会有一个对应的Application对象,这个LoadedApk一一对应。

下面分别以下两种进程创建Application的过程:

  • system_server进程;
  • app进程;

二. system_server进程

2.1 SystemServer.run

[-> SystemServer.java]

public final class SystemServer {
    private void run() {
        ...
        createSystemContext(); //[见2.2]
        ...
        startBootstrapServices();
        ...
    }
}

2.2 createSystemContext

[-> SystemServer.java]

private void createSystemContext() {
    ActivityThread activityThread = ActivityThread.systemMain(); //[见2.3]
    mSystemContext = activityThread.getSystemContext();  //[见2.x]
    ...
}

2.3 AT.systemMain

[-> ActivityThread.java]

public static ActivityThread systemMain() {
    ...
    ActivityThread thread = new ActivityThread();  //[见2.4]
    thread.attach(true);  //[见2.5]
    return thread;
}

2.4 AT初始化

[-> ActivityThread.java]

public final class ActivityThread {
    //创建ApplicationThread对象
    final ApplicationThread mAppThread = new ApplicationThread();
    final Looper mLooper = Looper.myLooper();
    final H mH = new H();
    //当前进程中首次初始化的app对象
    Application mInitialApplication;
    final ArrayList<Application> mAllApplications;
    //标记当前进程是否为system进程
    boolean mSystemThread = false;
    //记录system进程的ContextImpl对象
    private ContextImpl mSystemContext;

    final ArrayMap<String, WeakReference<LoadedApk>> mPackages;
    static Handler sMainThreadHandler;
    private static ActivityThread sCurrentActivityThread;

    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
    }
}

其中mInitialApplication的赋值过程分两种场景:

  • system_server进程是由ActivityThread.attach()过程赋值;
  • 普通app进程是由是由ActivityThread.handleBindApplication()过程赋值;这是进程刚创建后attach到system_server后, 便会binder call到app进程来执行该方法.

AT.currentApplication返回的便是mInitialApplication对象。创建完ActivityThread对象,接下来执行attach()操作。

2.5 AT.attach

[-> ActivityThread.java]

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system; //设置mSystemThread为true
    if (!system) {
        ...
    } else { //system进程才执行该流程
        //创建Instrumentation
        mInstrumentation = new Instrumentation();
        //[见小节2.6]
        ContextImpl context = ContextImpl.createAppContext(
                this, getSystemContext().mPackageInfo);
        //[见小节2.7]
        mInitialApplication = context.mPackageInfo.makeApplication(true, null);
        mInitialApplication.onCreate();
        ...
    }
}

attach的主要功能:

  • 根据LoadedApk对象来创建ContextImpl,对于system进程LoadedApk对象取值为mSystemContext;
  • 初始化Application信息。

2.6 CI.createAppContext

[-> ContextImpl.java]

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    //[见小节2.6.4]
    return new ContextImpl(null, mainThread,
            packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
}

创建ContextImpl对象有多种方法,常见的有:

createSystemContext(ActivityThread mainThread)
createAppContext(ActivityThread mainThread, LoadedApk packageInfo)
createApplicationContext(ApplicationInfo application, int flags)
createPackageContext(String packageName, int flags)

packageInfo是getSystemContext().mPackageInfo,所以先来看看getSystemContext过程。

2.6.1 AT.getSystemContext

public ContextImpl getSystemContext() {
    synchronized (this) {
        if (mSystemContext == null) {
            mSystemContext = ContextImpl.createSystemContext(this);
        }
        return mSystemContext;
    }
}

单例模式创建mSystemContext对象。

2.6.2 CI.createSystemContext

static ContextImpl createSystemContext(ActivityThread mainThread) {
    //创建LoadedApk对象 【见小节2.6.3】
    LoadedApk packageInfo = new LoadedApk(mainThread);
    // 创建ContextImpl【见小节2.6.4】
    ContextImpl context = new ContextImpl(null, mainThread,
            packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
    ...
    return context;
}

2.6.3 LoadedApk初始化

public final class LoadedApk {
    private final ActivityThread mActivityThread;
    private ApplicationInfo mApplicationInfo;
    private Application mApplication;
    final String mPackageName;
    private final ClassLoader mBaseClassLoader;
    private ClassLoader mClassLoader;

    LoadedApk(ActivityThread activityThread) {
        mActivityThread = activityThread; //ActivityThread对象
        mApplicationInfo = new ApplicationInfo(); //创建ApplicationInfo对象
        mApplicationInfo.packageName = "android";
        mPackageName = "android";  //默认包名为"android"
        ...
        mBaseClassLoader = null;
        mClassLoader = ClassLoader.getSystemClassLoader(); //创建ClassLoader
        ...
    }
}

只有一个参数的LoadedApk构造方法只有createSystemContext()过程才会创建, 其中LoadedApk初始化过程会创建ApplicationInfo对象,且包名为“android”。 创建完LoadedApk对象,接下里创建ContextImpl对象。

2.6.4 ContextImpl初始化

class ContextImpl extends Context {
    final ActivityThread mMainThread;
    final LoadedApk mPackageInfo;
    private final IBinder mActivityToken;
    private final String mBasePackageName;
    private Context mOuterContext;
    //缓存Binder服务
    final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();

    private ContextImpl(ContextImpl container, ActivityThread mainThread,
            LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
            Display display, Configuration overrideConfiguration, int createDisplayWithId) {
        mOuterContext = this; //ContextImpl对象
        mMainThread = mainThread; // ActivityThread赋值
        mPackageInfo = packageInfo; // LoadedApk赋值
        mBasePackageName = packageInfo.mPackageName; //mBasePackageName等于“android”
        ...
    }
}

首次执行getSystemContext,会创建LoadedApk和contextImpl对象,接下来利用刚创建的LoadedApk对象来创建新的ContextImpl对象。

2.7 makeApplication

[-> LoadedApk.java]

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    //保证一个LoadedApk对象只创建一个对应的Application对象
    if (mApplication != null) {
        return mApplication;
    }

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application"; //system_server进程, 则进入该分支
    }

    //创建ClassLoader对象【见小节2.8】
    java.lang.ClassLoader cl = getClassLoader();
    if (!mPackageName.equals("android")) {
        initializeJavaContextClassLoader();  //[见小节2.9]
    }

    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    //创建Application对象[见2.10]
    Application app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    appContext.setOuterContext(app);
    ...

    mActivityThread.mAllApplications.add(app);
    mApplication = app; //将刚创建的app赋值给mApplication
    ...
    return app;
}

2.8 getClassLoader

[-> LoadedApk.java]

public ClassLoader getClassLoader() {
    synchronized (this) {
        if (mClassLoader != null) {
            return mClassLoader;
        }

        if (mPackageName.equals("android")) {
            if (mBaseClassLoader == null) {
                //创建Classloader对象
                mClassLoader = ClassLoader.getSystemClassLoader();
            } else {
                mClassLoader = mBaseClassLoader;
            }
            return mClassLoader;
        }

        // 当包名不为"android"的情况
        if (mRegisterPackage) {
            //【见小节2.8.1】
            ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
        }

        zipPaths.add(mAppDir);
        libPaths.add(mLibDir);
        apkPaths.addAll(zipPaths);
        ...

        if (mApplicationInfo.isSystemApp()) {
            isBundledApp = true;
            //对于系统app,则添加vendor/lib, system/lib库
            libPaths.add(System.getProperty("java.library.path"));
            ...
        }

        final String zip = TextUtils.join(File.pathSeparator, zipPaths);

        //获取ClassLoader对象【见小节2.8.2】
        mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
                mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                libraryPermittedPath, mBaseClassLoader);
        return mClassLoader;
    }
}

2.8.1 AMS.addPackageDependency

public void addPackageDependency(String packageName) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        if (callingPid == Process.myPid()) {
            return;
        }
        ProcessRecord proc;
        synchronized (mPidsSelfLocked) {
            //查询的进程
            proc = mPidsSelfLocked.get(Binder.getCallingPid());
        }
        if (proc != null) {
            if (proc.pkgDeps == null) {
                proc.pkgDeps = new ArraySet<String>(1);
            }
            //将当前
            proc.pkgDeps.add(packageName);
        }
    }
}

2.8.2 AL.getClassLoader

[-> ApplicationLoaders.java]

public ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
                              String librarySearchPath, String libraryPermittedPath,
                              ClassLoader parent) {
    //获取父类的类加载器
    ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();

    synchronized (mLoaders) {
        if (parent == null) {
            parent = baseParent;
        }

        if (parent == baseParent) {
            ClassLoader loader = mLoaders.get(zip);
            if (loader != null) {
                return loader;
            }
            //创建PathClassLoader对象
            PathClassLoader pathClassloader = PathClassLoaderFactory.createClassLoader(
                                          zip,
                                          librarySearchPath,
                                          libraryPermittedPath,
                                          parent,
                                          targetSdkVersion,
                                          isBundled);
            //
            mLoaders.put(zip, pathClassloader);
            return pathClassloader;
        }

        PathClassLoader pathClassloader = new PathClassLoader(zip, parent);
        return pathClassloader;
    }
}

2.9 initializeJavaContextClassLoader

[-> LoadedApk.java]

private void initializeJavaContextClassLoader() {
    IPackageManager pm = ActivityThread.getPackageManager();
    android.content.pm.PackageInfo pi;
    pi = pm.getPackageInfo(mPackageName, 0, UserHandle.myUserId());

    boolean sharedUserIdSet = (pi.sharedUserId != null);
    boolean processNameNotDefault =
        (pi.applicationInfo != null &&
         !mPackageName.equals(pi.applicationInfo.processName));
    boolean sharable = (sharedUserIdSet || processNameNotDefault);
    ClassLoader contextClassLoader =
        (sharable)
        ? new WarningContextClassLoader()
        : mClassLoader;
    //设置当前线程的Context ClassLoader
    Thread.currentThread().setContextClassLoader(contextClassLoader);
}

2.10 newApplication

[-> Instrumentation.java]

public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    return newApplication(cl.loadClass(className), context);
}

2.10.1 newApplication

[-> Instrumentation.java]

static public Application newApplication(Class<?> clazz, Context context)
       throws InstantiationException, IllegalAccessException,
       ClassNotFoundException {
   Application app = (Application)clazz.newInstance(); //【见小节2.10.2】
   app.attach(context); //【见小节2.10.3】
   return app;
}

2.10.2 Application初始化

[-> Application.java]

public class Application extends ContextWrapper implements ComponentCallbacks2 {
    public LoadedApk mLoadedApk;

    public Application() {
        super(null);
    }
}

2.10.3 App.attach

[-> Application.java]

final void attach(Context context) {
    attachBaseContext(context); //Application的mBase
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

该方法主要功能:

  1. 将新创建的ContextImpl对象保存到Application的父类成员变量mBase;
  2. 将新创建的LoadedApk对象保存到Application的父员变量mLoadedApk;

三. App进程

3.1 ActivityThread.main

[-> ActivityThread.java]

public static void main(String[] args) {
    ,,,
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    ,,,
}

这是运行在app进程

3.2 AT.attach

[-> ActivityThread.java]

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        //初始化RuntimeInit.mApplicationObject值
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        mgr.attachApplication(mAppThread); //
    } else {
        ...
    }
}

3.3 AMS.attachApplicationLocked

[-> ActivityManagerService.java]

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {
    ProcessRecord app;
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid); // 根据pid获取ProcessRecord
        }
    }

    ...
    ApplicationInfo appInfo = app.instrumentationInfo != null
            ? app.instrumentationInfo : app.info;
    //[见流程3.4]
    thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
            profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
            app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
            isRestrictedBackupMode || !normalMode, app.persistent,
            new Configuration(mConfiguration), app.compat,
            getCommonServicesLocked(app.isolated),
            mCoreSettingsObserver.getCoreSettingsLocked());
    ...

    return true;
}

system_server收到attach操作, 然后再向新创建的进程执行handleBindApplication()过程:

3.4 AT.handleBindApplication

[-> ActivityThread.java ::H]

当主线程收到H.BIND_APPLICATION,则调用handleBindApplication

private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
    Process.setArgV0(data.processName);//设置进程名
    ...
    //获取LoadedApk对象[见小节3.5]
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...

    // 创建ContextImpl上下文[2.6.4]
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    ...

    try {
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象[见小节2.7]
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        mInstrumentation.onCreate(data.instrumentationArgs);
        mInstrumentation.callApplicationOnCreate(app);

    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

在handleBindApplication()的过程中,会同时设置以下两个值:

  • LoadedApk.mApplication
  • ActivityThread.mInitialApplication

3.5 getPackageInfoNoCheck

[-> ActivityThread.java]

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
        CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}

private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
    ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
        boolean registerPackage) {
    final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
    synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
        if (differentUser) {
            ref = null;
        } else if (includeCode) {
            ref = mPackages.get(aInfo.packageName); //从mPackages查询
        } else {
            ...
        }

        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            //创建LoadedApk对象
            packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

            if (mSystemThread && "android".equals(aInfo.packageName)) {
                ...
            }

            if (differentUser) {
                ...
            } else if (includeCode) {
                //将新创建的LoadedApk加入到mPackages
                mPackages.put(aInfo.packageName,
                        new WeakReference<LoadedApk>(packageInfo));
            } else {
                ...
            }
        }
        return packageInfo;
    }
}

创建LoadedApk对象,并将将新创建的LoadedApk加入到mPackages. 也就是说每个app都会创建唯一的LoadedApk对象. 此处aInfo来源于ProcessRecord.info变量, 也就是进程中的第一个app.

App进程的Application创建过程,跟system进程的核心逻辑都差不多。只是app进程的多了两次binder调用。

理解Android Context

$
0
0

一. 概述

接触过Android的小伙伴, 一定不会对Context感到陌生, 有大量的场景使用都离不开Context, 下面列举部分常见场景:

  • 启动Activity (startActivity)
  • 启动服务 (startService)
  • 发送广播 (sendBroadcast), 注册广播接收者 (registerReceiver)
  • 获取ContentResolver (getContentResolver)
  • 获取类加载器 (getClassLoader)
  • 打开或创建数据库 (openOrCreateDatabase)
  • 获取资源 (getResources)

四大组件,各种资源操作以及其他很多场景都离不开Context, 那么Context到底是何方神圣呢? 中文意思为上下文, 顾名思义就是在某一个场景中本身所包含的一些潜在信息. 举个例子来说明, 比如当下你正在看Gityuan博客 作为一个Context, 那么这个上下文就会隐藏 博客作者, 博客网址, 博客目录等信息, 其中通过Contet.getAuthor()就能返回”Gityuan”. 这就是上下文, 某一个场景背后所隐藏的信息.

回到主题, Android Context本身是一个抽象类. ContextImpl, Activity, Service, Application这些都是Context的直接或间接子类, 下面通过看看这些类的关系,如下: 点击查看大图

context

图解:

  1. Application, Activity, Service都会通过attach()方法会调用到ContextWrapper的attachBaseContext; 从而设置其父类ContextWrapper的成员变量mBase值为ContextImpl对象;ContextWrapper的核心工作都是交给mBase来完成, 也就是ContextImpl类.
  2. Android四大组件都会属于某一个Application,那么这些组件获取Application的途径:
    • Activity/Service: 是通过调用其方法getApplication(),可主动获取当前所在mApplication;
      • mApplication是由LoadedApk.makeApplication()过程所初始化的;
    • Receiver: 是通过其方法onReceive()的第一个参数指向通当前所在Application,也就是只有接收到广播的时候才能拿到当前的Application对象;
    • provider: 目前没有提供直接获取当前所在Application的方法, 但可通过getContext()可以获取当前的ContextImpl.

二. 组件分析

要理解Context, 需要依次来看看四大组件的初始化过程.

2.1 Activity

[-> ActivityThread.java]

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        //step 1: 创建LoadedApk对象
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }
    ... //component初始化过程

    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    //step 2: 创建Activity对象
    Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    ...

    //step 3: 创建Application对象
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);

    if (activity != null) {
        //step 4: 创建ContextImpl对象
        Context appContext = createBaseContextForActivity(r, activity);
        CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
        Configuration config = new Configuration(mCompatConfiguration);
        //step5: 将Application/ContextImpl都attach到Activity对象 [见小节4.3.1]
        activity.attach(appContext, this, getInstrumentation(), r.token,
                r.ident, app, r.intent, r.activityInfo, title, r.parent,
                r.embeddedID, r.lastNonConfigurationInstances, config,
                r.referrer, r.voiceInteractor);

        ...
        int theme = r.activityInfo.getThemeResource();
        if (theme != 0) {
            activity.setTheme(theme);
        }

        activity.mCalled = false;
        if (r.isPersistable()) {
            //step 6: 执行回调onCreate
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }

        r.activity = activity;
        r.stopped = true;
        if (!r.activity.mFinished) {
            activity.performStart(); //执行回调onStart
            r.stopped = false;
        }
        if (!r.activity.mFinished) {
            //执行回调onRestoreInstanceState
            if (r.isPersistable()) {
                if (r.state != null || r.persistentState != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                            r.persistentState);
                }
            } else if (r.state != null) {
                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
            }
        }
        ...
        r.paused = true;
        mActivities.put(r.token, r);
    }

    return activity;
}

startActivity的过程最终会在目标进程执行performLaunchActivity()方法, 该方法主要功能:

  1. 创建对象LoadedApk;
  2. 创建对象Activity;
  3. 创建对象Application;
  4. 创建对象ContextImpl;
  5. Application/ContextImpl都attach到Activity对象;
  6. 执行onCreate()等回调;

2.2 Service

[-> ActivityThread.java]

private void handleCreateService(CreateServiceData data) {
    ...
    //step 1: 创建LoadedApk
    LoadedApk packageInfo = getPackageInfoNoCheck(
        data.info.applicationInfo, data.compatInfo);

    java.lang.ClassLoader cl = packageInfo.getClassLoader();
    //step 2: 创建Service对象
    service = (Service) cl.loadClass(data.info.name).newInstance();

    //step 3: 创建ContextImpl对象
    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
    context.setOuterContext(service);

    //step 4: 创建Application对象
    Application app = packageInfo.makeApplication(false, mInstrumentation);

    //step 5: 将Application/ContextImpl都attach到Activity对象 [见小节4.3.2]
    service.attach(context, this, data.info.name, data.token, app,
            ActivityManagerNative.getDefault());

    //step 6: 执行onCreate回调
    service.onCreate();
    mServices.put(data.token, service);
    ActivityManagerNative.getDefault().serviceDoneExecuting(
            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
    ...
}

整个过程:

  1. 创建对象LoadedApk;
  2. 创建对象Service;
  3. 创建对象ContextImpl;
  4. 创建对象Application;
  5. Application/ContextImpl分别attach到Service对象;
  6. 执行onCreate()回调;

2.3 BroadcastReceiver

[-> ActivityThread.java]

private void handleReceiver(ReceiverData data) {
    ...
    String component = data.intent.getComponent().getClassName();
    //step 1: 创建LoadedApk对象
    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);

    IActivityManager mgr = ActivityManagerNative.getDefault();
    java.lang.ClassLoader cl = packageInfo.getClassLoader();
    data.intent.setExtrasClassLoader(cl);
    data.intent.prepareToEnterProcess();
    data.setExtrasClassLoader(cl);
    //step 2: 创建BroadcastReceiver对象
    BroadcastReceiver receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();

    //step 3: 创建Application对象
    Application app = packageInfo.makeApplication(false, mInstrumentation);

    //step 4: 创建ContextImpl对象
    ContextImpl context = (ContextImpl)app.getBaseContext();
    sCurrentBroadcastIntent.set(data.intent);
    receiver.setPendingResult(data);

    //step 5: 执行onReceive回调 [见小节4.3.3]
    receiver.onReceive(context.getReceiverRestrictedContext(), data.intent);
    ...
}

整个过程:

  1. 创建对象LoadedApk;
  2. 创建对象BroadcastReceiver;
  3. 创建对象Application;
  4. 创建对象ContextImpl;
  5. 执行onReceive()回调;

2.4 Provider

[-> ActivityThread.java]

private IActivityManager.ContentProviderHolder installProvider(Context context,
        IActivityManager.ContentProviderHolder holder, ProviderInfo info,
        boolean noisy, boolean noReleaseNeeded, boolean stable) {
    ContentProvider localProvider = null;
    IContentProvider provider;
    if (holder == null || holder.provider == null) {
        Context c = null;
        ApplicationInfo ai = info.applicationInfo;
        if (context.getPackageName().equals(ai.packageName)) {
            c = context;
        } else if (mInitialApplication != null &&
                mInitialApplication.getPackageName().equals(ai.packageName)) {
            c = mInitialApplication;
        } else {
            //step 1/2: 创建LoadedApk和ContextImpl对象
            c = context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);
        }

        final java.lang.ClassLoader cl = c.getClassLoader();
        //step 3: 创建ContentProvider对象
        localProvider = (ContentProvider)cl.loadClass(info.name).newInstance();
        provider = localProvider.getIContentProvider();

        //step 4/5: ContextImpl都attach到ContentProvider对象,并执行回调onCreate [见小节4.3.4]
        localProvider.attachInfo(c, info);
    } else {
        ...
    }
    ...
    return retHolder;
}

该方法主要功能:

  1. 创建对象LoadedApk;
  2. 创建对象ContextImpl;
  3. 创建对象ContentProvider;
  4. ContextImpl都attach到Service对象;
  5. 执行onCreate回调;

2.5 Application

[-> ActivityThread.java]

private void handleBindApplication(AppBindData data) {
    //step 1: 创建LoadedApk对象
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...
    //step 2: 创建ContextImpl对象;
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

    //step 3: 创建Instrumentation
    mInstrumentation = new Instrumentation();

    //step 4: 创建Application对象; [见小节3.2]
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    mInitialApplication = app;

    //step 5: 安装providers
    List<ProviderInfo> providers = data.providers;
    installContentProviders(app, providers);

    //step 6: 执行Application.Create回调
    mInstrumentation.callApplicationOnCreate(app);

该过程主要功能:

  1. 创建对象LoadedApk
  2. 创建对象ContextImpl;
  3. 创建对象Instrumentation;
  4. 创建对象Application;
  5. 安装providers;
  6. 执行Create回调;

三. 原理分析

上面介绍了4大组件以及Application的初始化过程, 接下来再进一步说明其中LoadedApk, ContextImpl, Application的初始化过程.

3.1 创建LoadedApk

3.1.1 AT.getPackageInfo

[-> ActivityThread.java]

public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
        int flags) {
    boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
    //是否违反隐私问题
    boolean securityViolation = includeCode && ai.uid != 0
            && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
                    ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
                    : true);
    boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;
    ...
    return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
            registerPackage);
}

当securityViolation=true,则代表违反隐私问题, 会抛出SecurityException异常.

3.1.2 AT.getPackageInfo

[-> ActivityThread.java]

private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
    ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
        boolean registerPackage) {
    final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
    synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
        if (differentUser) {
            ref = null;
        } else if (includeCode) {
            ref = mPackages.get(aInfo.packageName); //从mPackages查询
        } else {
            ...
        }

        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            //创建LoadedApk对象, 此时baseLoader为null
            packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
            ...

            if (differentUser) {
                ...
            } else if (includeCode) {
                //将新创建的LoadedApk加入到mPackages
                mPackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo));
            } else {
                ...
            }
        }
        return packageInfo;
    }
}

该方法主要功能:

  • mPackages的数据类型为ArrayMap<String, WeakReference>,记录着每一个包名所对应的LoadedApk对象的弱引用;
  • 当mPackages没有找到相应的LoadedApk对象, 则创建该对象并加入到mPackages.

3.1.3 AT.getPackageInfoNoCheck

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
        CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}

除了Activity的初始化, 其他组件初始化都是采用该方法,有默认参数值, 主要功能还是一致的.

  • securityViolation=false,则不进行是否违反隐私的监测;
  • registerPackage=false, 则在获取类加载器(getClassLoader)时,不会将该package添加到当前所在进程的成员变量pkgDeps.

3.2 创建Application

有了LoadedApk对象, 接下来可以创建Application对象, 该对象一个Apk只会创建一次.

3.2.1 LoadedApk.makeApplication

[-> LoadedApk.java]

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    //保证一个LoadedApk对象只创建一个对应的Application对象
    if (mApplication != null) {
        return mApplication;
    }

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application"; //设置应用类名
    }


    java.lang.ClassLoader cl = getClassLoader();
    if (!mPackageName.equals("android")) {
        initializeJavaContextClassLoader();
    }

    //创建ContextImpl对象
    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    //创建Application对象, 并将appContext attach到新创建的Application[见3.2.2]
    Application app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    appContext.setOuterContext(app);
    ...

    mActivityThread.mAllApplications.add(app);
    mApplication = app; //将刚创建的app赋值给mApplication
    ...
    return app;
}

该方法主要功能:

  1. 获取当前应用的ClassLoader对象,根据是否为”android”来决定调用initializeJavaContextClassLoader()的过程;
  2. 根据当前ActivityThread对象来创建相应的ContextImpl对象
  3. 创建Application对象, 初始化其成员变量:
    • mBase指向新创建ContextImpl;
    • mLoadedApk指向当前所在的LoadedApk对象;
  4. 将新创建的Application对象保存到ContextImpl的成员变量mOuterContext.

关于initializeJavaContextClassLoader()的过程, 见文章理解Application初始化的[小节2.9].

关于应用类名采用的是Apk中声明的应用类名,即Manifest.xml中定义的类名. 有两种特殊情况会强制 设置应用类名为”android.app.Application”:

  • 当forceDefaultAppClass=true, 目前只有system_server进程初始化包名为”android”的apk过程会调用;
  • Apk没有自定义应用类名的情况.

3.2.2 newApplication

[-> Instrumentation.java]

static public Application newApplication(Class<?> clazz, Context context)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    Application app = (Application)clazz.newInstance(); //创建Application
    app.attach(context); //执行attach操作[见小节4.3.5]
    return app;
}

3.3 创建ContextImpl

创建ContextImpl的方式有多种, 不同的组件初始化调用不同的方法,如下:

  • Activity: 调用createBaseContextForActivity初始化;
  • Service/Application: 调用createAppContext初始化;
  • Provider: 调用createPackageContext初始化;
  • BroadcastReceiver: 直接从Application.getBaseContext()来获取ContextImpl对象;

3.3.1 createBaseContextForActivity

[-> ActivityThread.java]

private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
    int displayId = Display.DEFAULT_DISPLAY;
    try {
        displayId = ActivityManagerNative.getDefault().getActivityDisplayId(r.token);
    } catch (RemoteException e) {
    }

    //创建ContextImpl对象
    ContextImpl appContext = ContextImpl.createActivityContext(
            this, r.packageInfo, displayId, r.overrideConfig);
    appContext.setOuterContext(activity);
    Context baseContext = appContext;
    ...

    return baseContext;
}

[-> ContextImpl.java]

static ContextImpl createActivityContext(ActivityThread mainThread,
        LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
    return new ContextImpl(null, mainThread, packageInfo,
            null, null, false,
            null, overrideConfiguration, displayId);
}

Activity采用该方法来初始化ContextImpl对象.

3.3.2 createAppContext

[-> ContextImpl.java]

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    return new ContextImpl(null, mainThread, packageInfo,
             null, null, false,
             null, null, Display.INVALID_DISPLAY);
}

Service/Application采用该方法来初始化ContextImpl对象.

3.3.3 createPackageContext

[-> ContextImpl.java]

public Context createPackageContext(String packageName, int flags)
        throws NameNotFoundException {
    return createPackageContextAsUser(packageName, flags,
            mUser != null ? mUser : Process.myUserHandle());
}

public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
        throws NameNotFoundException {
    final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
    if (packageName.equals("system") || packageName.equals("android")) {
        return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
                user, restricted, mDisplay, null, Display.INVALID_DISPLAY);
    }

    //创建LoadedApk
    LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
            flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
    if (pi != null) {
        //创建ContextImpl
        ContextImpl c = new ContextImpl(this, mMainThread, pi,
                mActivityToken,user, restricted,
                mDisplay, null, Display.INVALID_DISPLAY);
        if (c.mResources != null) {
            return c;
        }
    }

}

provider采用该方法来初始化ContextImpl对象.

3.3.4 ContextImpl初始化

[-> ContextImpl.java]

class ContextImpl extends Context {
    final ActivityThread mMainThread;
    final LoadedApk mPackageInfo;
    private final IBinder mActivityToken;
    private final String mBasePackageName;
    private Context mOuterContext;
    //缓存Binder服务
    final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();

    private ContextImpl(ContextImpl container, ActivityThread mainThread,
            LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
            Display display, Configuration overrideConfiguration, int createDisplayWithId) {
        mOuterContext = this; //ContextImpl对象
        mMainThread = mainThread; // ActivityThread赋值
        mPackageInfo = packageInfo; // LoadedApk赋值
        mBasePackageName = packageInfo.mPackageName; //mBasePackageName等于“android”
        ...
    }
}

四. Context对比

4.1 Context核心方法

再来说说Context相关的几个核心方法:

对象方法含义返回值类型
ActivitygetApplication()获取当前所在应用mApplicationApplication
ServicegetApplication()获取当前所在应用mApplicationApplication
ContextWrappergetApplicationContext等价于ContextImpl的getApplicationContext()Application
ContextImplgetApplicationContextmPackageInfo.mApplication或者mMainThread.mInitialApplicationApplication
ContextWrappergetBaseContext获取mBaseContextImpl
ContextImplgetOuterContext获取mOuterContextContextImpl
ContextImplgetApplicationInfomPackageInfo.mApplicationInfoApplicationInfo

Tips:

  • ContextImpl的mOuterContext指向外部的Context, 一般地为Application/Activity/Service对象.对于BroadcastReceiver和Provider
  • getApplication()和getApplicationContext()这两个方法在大多数情况下是一致的,

4.2 getApplicationContext

[-> ContextImpl.java]

public Context getApplicationContext() {
    return (mPackageInfo != null) ?
            mPackageInfo.getApplication() : mMainThread.getApplication();
}

说明:

  1. mPackageInfo.getApplication(): 返回的是LoadedApk.mApplication
    • Activity/Servie/BroadcastReceiver/Application初始化过程都调用makeApplication()赋值;
  2. mMainThread.getApplication(): 返回的是AT.mInitialApplication
    • AT.handleBindApplication()赋值;
    • system_server进程的AT.attach()赋值;

4.3 attach过程对比

4.3.1 Activity

[-> Activity.java]

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    attachBaseContext(context); //调用父类方法设置mBase.
    mUiThread = Thread.currentThread();
    mMainThread = aThread;
    mApplication = application;
    mIntent = intent;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    ...
}

将新创建的ContextImpl赋值到父类ContextWrapper.mBase变量.

4.3.2 Service

[-> Service.java]

public final void attach(
        Context context,
        ActivityThread thread, String className, IBinder token,
        Application application, Object activityManager) {
    attachBaseContext(context); //调用父类方法设置mBase.
    mClassName = className;
    mToken = token;
    mApplication = application;
    ...
}

将新创建的ContextImpl赋值到父类ContextWrapper.mBase变量.

4.3.3 BroadcastReceiver

[-> ContextImpl.java]

final Context getReceiverRestrictedContext() {
    if (mReceiverRestrictedContext != null) {
        return mReceiverRestrictedContext;
    }
    return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
}

对于广播来说Context的传递过程, 跟其他组件完全不同. 广播是在onCreate过程通过参数将ReceiverRestrictedContext传递过去的.

4.3.4 ContentProvider

[-> ContentProvider.java]

public void attachInfo(Context context, ProviderInfo info) {
    attachInfo(context, info, false);
}

private void attachInfo(Context context, ProviderInfo info, boolean testing) {
    mNoPerms = testing;

    if (mContext == null) {
        //将新创建ContextImpl对象保存到ContentProvider对象的成员变量mContext
        mContext = context;
        ...
        if (info != null) {
            setReadPermission(info.readPermission);
            setWritePermission(info.writePermission);
            setPathPermissions(info.pathPermissions);
            mExported = info.exported;
            mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0;
            setAuthorities(info.authority);
        }
        // 执行onCreate回调;
        ContentProvider.this.onCreate();
    }
}

该方法主要功能:

  • 将新创建ContextImpl对象保存到ContentProvider对象的成员变量mContext;
    • 可通过getContext()获取该ContextImpl;
  • 执行onCreate回调;

3.3.5 Application

[-> Application.java]

final void attach(Context context) {
    attachBaseContext(context); //Application的mBase
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

该方法主要功能:

  1. 将新创建的ContextImpl对象保存到Application的父类成员变量mBase;
  2. 将当前所在的LoadedApk对象保存到Application的父员变量mLoadedApk;

五. 总结

(一) 下面用一幅图来看看核心组件的初始化过程会创建哪些对象:

类型LoadedApkContextImplApplication创建相应对象回调方法
ActivityActivityonCreate
ServiceServiceonCreate
ReceiverBroadcastReceiveronReceive
Provider×ProvideronCreate
ApplicationApplicationonCreate

每个Apk都对应唯一的application对象和LoadedApk对象, 当Apk中任意组件的创建过程中, 当其所对应的的LoadedApk和Application没有初始化则会创建, 且只会创建一次.

另外大家会注意到唯有Provider在初始化过程并不会去创建所相应的Application对象.也就意味着当有多个Apk运行在同一个进程的情况下, 第二个apk通过Provider初始化过程再调用getContext().getApplicationContext()返回的并非Application对象, 而是NULL. 这里要注意会抛出空指针异常.

(二) 关于Context attach过程:

  • Activity/Service/Application: 调用attachBaseContext(), 将新创建的ContextImpl赋值到父类ContextWrapper.mBase变量;
    • 可通过getBaseContext()获取该ContextImpl;
  • ContentProvider: 调用attachInfo(),将新创建ContextImpl对象保存到ContentProvider对象的成员变量mContext;
    • 可通过getContext()获取该ContextImpl;
  • BroadcastReceiver: 在onCreate过程通过参数将ReceiverRestrictedContext传递过去的.

(三) 最后, 说一说Context的使用场景

类型startActivitystartServicebindServicesendBroadcastregisterReceivergetContentResolver
Activity
Service-
Receiver-×-
Provider-
Application-

说明:

  • Receiver不允许bindService, 这是由于限制性上下文(ReceiverRestrictedContext)所决定的,会直接抛出异常.
  • Receiver: registerReceiver是否允许使用取决于receiver;
    • 当receiver == null用于获取sticky广播, 允许使用;
    • 否则,不允许使用registerReceiver;
  • startActivity在Activity中可正常使用, 如果是其他组件的话需要startActivity则必须带上FLAG_ACTIVITY_NEW_TASK flags.
  • 另外UI相关则要Activity中使用.

简述Activity与Window关系

$
0
0

一. 概述

AMS是Android系统最为核心的服务之一,其职责包括四大核心组件与进程的管理,而四大组件中Activity最为复杂。 其复杂在于需要跟用户进行UI交互(涉及Window),WMS其主要职责便是窗口管理,还有跟App,SurfaceFlinger等 模块间相互协同工作。简而言之:

  • App主要是具体的UI业务需求
  • AMS则是管理系统四大组件以及进程管理,尤其是Activity的各种栈以及状态切换等管理;
  • WMS则是管理Activiy所相应的窗口系统(系统窗口以及嵌套的子窗口);
  • SurfaceFlinger则是将应用UI绘制到frameBuffer(帧缓冲区),最终由硬件完成渲染到屏幕上;

1.1 WMS全貌

wms_relation

说明: 点击查看大图

  • WMS继承于IWindowManager.Stub, 作为Binder服务端;
  • WMS的成员变量mSessions保存着所有的Session对象,Session继承于IWindowSession.Stub, 作为Binder服务端;
  • 成员变量mPolicy: 实例对象为PhoneWindowManager,用于实现各种窗口相关的策略;
  • 成员变量mChoreographer: 用于控制窗口动画,屏幕旋转等操作;
  • 成员变量mDisplayContents: 记录一组DisplayContent对象,这个跟多屏输出相关;
  • 成员变量mTokenMap: 保存所有的WindowToken对象; 以IBinder为key,可以是IAppWindowToken或者其他Binder的Bp端;
    • 另一端情况:ActivityRecord.Token extends IApplicationToken.Stub
  • 成员变量mWindowMap: 保存所有的WindowState对象;以IBinder为key, 是IWindow的Bp端;
    • 另一端情况: ViewRootImpl.W extends IWindow.Stub
  • 一般地,每一个窗口都对应一个WindowState对象, 该对象的成员变量mClient用于跟应用端交互,成员变量mToken用于跟AMS交互.

二. Activity与Window

2.1 Binder服务

wms_binder

上图是Window调用过程所涉及的Binder服务:

Binder服务端接口所在进程
WindowManagerServiceIWindowManagersystem_server
SessionIWindowSessionsystem_server
ViewRootImpl.WIWindowapp进程
ActivityRecord.TokenIApplicationTokensystem_server

Activity启动过程会执行组件的生命周期回调以及UI相关对象的创建。UI工作通过向AMS服务来 创建WindowState对象完成,该对象用于描述窗口各种状态属性,以及跟WMS通信。

  1. WindowManagerService: Activity通过其成员变量mWindowManager(数据类型WindowManagerImpl),再调用WindowManagerGlobal对象,经过binder call跟WMS通信;
  2. Session:ViewRootImp创建的用于跟WMS中的Session进行通信;
  3. ViewRootImpl.W:app端创建的binder服务;
  4. ActivityRecord.Token: startActivity过程通过binder call进入system_server进程,在该进程执行ASS.startActivityLocked()方法中会创建相应的ActivityRecord对象,该对象初始化时会创建数据类型为ActivityRecord.Token的成员变量appToken,然后会将该对象传递到ActivityThread.

2.2 核心对象

2.2.1 Activity对象

[-> Activity.java]

下面列举Activity对象的部分常见成员变量:

  1. mWindow:数据类型为PhoneWindow,继承于Window对象;
  2. mWindowManager:数据类型为WindowManagerImpl,实现WindowManager接口;
  3. mMainThread:数据类型为ActivityThread, 并非真正的线程,只是运行在主线程的对象。
  4. mUiThread: 数据类型为Thread,当前activity所在线程,即主线程;
  5. mHandler:数据类型为Handler, 当前主线程的handler;
  6. mDecor: 数据类型为View, Activity执行完resume之后创建的视图对象;

另外说明:WindowManagerImpl与Window这两个对象相互保存对方的信息:

  • WindowManagerImpl.mParentWindowWindow 指向Window对象;
  • Window.mWindowManager 指向WindowManagerImpl对象;

2.2.2 ViewRootImpl对象

  1. mWindowSession: 数据类型为IWindowSession, 同一进程中所有的ViewRootImpl对象只对应唯一相同的Session代理对象。
  2. mWindow: 数据类型为IWindow.Stub,每个创建对应一个该对象。

2.2.3 WindowState对象

WindowState对象代表一个窗口,记录在system_server.

  • mSession: 数据类型为Session,是system_server的binder服务端;
  • mClient: 数据类型为IWindow,是app端的ViewRootImpl.W服务的binder代理对象;

2.3 数量关系

  1. 每一个Activity对应一个应用窗口;每一个窗口对应一个ViewRootImpl对象;
  2. 每一个App进程对应唯一的WindowManagerGlobal对象;
    • WindowManagerGlobal.sWindowManagerService用于跟WMS交互
    • WindowManagerGlobal.sWindowSession用于跟Session交互;
  3. 每一个App进程对应唯一的相同Session代理对象;
  4. App可以没有Activity/PhoneWindow/DecorView,例如带悬浮窗口的Service;
  5. Activity运行在ActivityThread所在的主线程;
  6. DecorView是Activity所要显示的视图内容;
  7. ViewRootImpl:管理DecorView跟WMS的交互;每次调用addView()添加窗口时,则都会创建一个ViewRootImpl对象;

2.4 AMS与WMS的对于关系

Activity与Window有一些对象具有一定的对应关系:

AMSWMS
ActivityRecordAppWindowToken
TaskRecordTask
ActivityStackTaskStack

2.5 交互

  • App跟AMS通信,会建立Session连接到WMS,后续便通过IWindowSesson跟WMS通信;
  • WMS跟SF通信,WMS建立SurfaceComposerClient,然后会在SF中创建Client与之对应, 后续便通过ISurfaceComposerClient跟SF通信;

2.6 IWindow死亡回调

[-> WindowState.java]

private class DeathRecipient implements IBinder.DeathRecipient {
    public void binderDied() {
        try {
            synchronized(mService.mWindowMap) {
                WindowState win = mService.windowForClientLocked(mSession, mClient, false);
                Slog.i(TAG, "WIN DEATH: " + win);
                if (win != null) {
                    mService.removeWindowLocked(win);
                } else if (mHasSurface) {
                    Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
                    mService.removeWindowLocked(WindowState.this);
                }
            }
        } catch (IllegalArgumentException ex) {
            ...
        }
    }
}

当App端进程死亡,运行在system_server的IWindow代理端会收到死亡回调,来处理移除相应的window信息。

三. 小结

还要重点聊一聊 主线程如何与UI交互。

未完待续…

四大组件之ProcessRecord

$
0
0

一. 引言

Android中,对于进程的概念被弱化,通过抽象后的四大组件。让开发者几乎感受不到进程的存在。 当应用退出时,进程也并非马上退出,而是成为cache/empty进程,下次该应用再启动的时候,可以不用 再创建进程直接初始化组件即可,提高启动速度。

Android系统中用于描述进程的数据结构是ProcessRecord对象,AMS便是管理进程的核心模块。四大组件 (Activity,Service, BroadcastReceiver, ContentProvider)定义在AndroidManifest.xml文件, 每一项都可以用属性android:process指定所运行的进程。同一个app可以运行在通过一个进程,也可以运行在多个进程, 甚至多个app可以共享同一个进程。例如:AndroidManifest.xml中定义Service:

<service android:name =".GityuanService"  android:process =":remote">  
    <intent-filter>  
       <action android:name ="com.action.gityuan" />  
    </intent-filter>  
</service>

GityuanService这个服务运行在remote进程。

二. 进程管理

先以一幅图来展示AMS管理进程的相关成员变量以及ProcessRecord对象:

点击查看大图

process_record

2.1 ActivityManagerService

这里只介绍AMS的进程相关的成员变量:

  1. mProcessNames:数据类型为ProcessMap,以进程名和userId为key来记录ProcessRecord;
    • 添加进程,addProcessNameLocked()
    • 删除进程,removeProcessNameLocked()
  2. mPidsSelfLocked: 数据类型为SparseArray,以进程pid为key来记录ProcessRecord;
    • startProcessLocked(),移除已存在进程,增加新创建进程pid信息;
    • removeProcessLocked,processStartTimedOutLocked,cleanUpApplicationRecordLocked移除进程;
  3. mLruProcesses:数据类型为ArrayList,以进程最近使用情况来排序记录ProcessRecord;
    • 其中第一个元素代表的便是最近最少使用的进程;
    • updateLruProcessLocked()更新进程队列位置;
  4. mRemovedProcesses:数据类型为ArrayList,记录所有需要强制移除的进程;
  5. mProcessesToGc:数据类型为ArrayList,记录当系统进入idle状态需要尽快执行gc操作的进程;
  6. mPendingPssProcesses:数据类型为ArrayList,记录即将要收集内存使用情况PSS数据的进程;
  7. mProcessesOnHold:数据类型为ArrayList,记录刚开机过程,系统还没与偶准备就绪的情况下, 所有需要启动的进程都放入到该队列;
  8. mPersistentStartingProcesses:数据类型ArrayList,正在启动的persistent进程;
  9. mHomeProcess: 记录包含home Activity所在的进程;
  10. mPreviousProcess:记录用户上一次刚访问的进程;其中mPreviousProcessVisibleTime记录上一个进程的用户访问时间;
  11. mProcessList: 数据类型ProcessList,用于进程管理,Adj常量定义位于该文件;

其中最为常见的是mProcessNames,mPidsSelfLocked,mLruProcesses这3个对象;

2.2 ProcessRecord

部分重要成员变量说明:

  1. info:记录运行在该进程的第一个应用;
  2. pkgList: 记录运行在该进程中所有的包名,比如通过addPackage()添加;
  3. pkgDeps:记录该进程所依赖的包名,比如通过addPackageDependency()添加;
  4. thread:执行完attachApplicationLocked()方法,会把客户端进程ApplicationThread的binder服务的代理端传递到 AMS,并保持到ProcessRecord的成员变量thread;
    • ProcessRecord.makeActive,赋值;
    • ProcessRecord.makeInactive,清空;
  5. lastActivityTime:每次updateLruProcessLocked()过程会更新该值;
  6. killedByAm:当值为true,意味着该进程是被AMS所杀,而非由于内存低而被LMK所杀;
  7. killed:当值为true,意味着该进程被杀,不论是AMS还是其他方式;
  8. waitingToKill:比如cleanUpRemovedTaskLocked()过程会赋值为”remove task”,当该进程处于后台且

四大组件都运行在某个进程,再来说说组件相关的成员变量:

  1. Activity:
    • activities:记录所有运行在该进程的ActivityRecord;
  2. Service
    • services: 记录所有运行在该进程的ServiceRecord;
    • executingServices: 记录所有当前正在执行的ServiceRecord;
    • connections: 记录当前进程bind的所有ConnectionRecord,即bind service的client进程;
  3. Receiver:
    • receivers: 所有动态注册的广播接收者ReceiverList;
    • curReceiver: 该进程当前正在处理的广播;
  4. ContentProvider:
    • pubProviders:记录该进程发布的provider;
    • conProviders:记录该进程所请求的provider;

四大组件之ServiceRecord

$
0
0

一. 引言

Android系统中最为重要的服务便是AMS, AMS管理着framework层面四大组件和进程. 本文从另一个维度 来说一说四大组件之一的Service. 每个app进程运行的Service, 对应于system_server进程中AMS的ServiceRecord对象. 也就是说所有app进程的Service, 都会记录在system_server进程, 好比一个大管家.

本文的重点是讲解AMS如何管理Service.

二. Service数据结构

先以一幅图来展示AMS管理Service所涉及的相关数据结构: 点击查看大图

service_record

图中,从上至下存在简单的包含关系:

  • ServiceRecord可以包含一个或多个IntentBindRecord;
  • IntentBindRecord可以包含一个或多个AppBindRecord;
  • AppBindRecord可以包含一个或多个ConnectionRecord;

2.1 ServiceRecord

ServiceRecord位于system_server进程,是AMS管理各个app中service的基本单位。 ServiceRecord继承于Binder对象,作为Binder IPC的Bn端;Binder将其传递到Service进程的Bp端, 保存在Service.mToken, 即ServiceRecord的代理对象。

ServiceRecord的成员变量app,用于记录当前service运行在哪个进程。再来说说其他成员变量:

(1)bindings:由于可通过不同的Intent来bind同一个service,故采用bindings来记录所有的intent以及对应的IntentBindRecord ,其数据类型如下:

ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings

(2)connections:记录IServiceConnection以及所有对应client的ConnectionRecord

(3)startRequested:代表service是否由startService方式所启动的

  • startService(),则startRequested=true;
  • stopService()或stopSelf(),则startRequested=false;

2.2 IntentBindRecord

功能: 一个绑定的Intent与其对应的service

(1)apps: 由于同一个intent,可能有多个不同的进程来bind该service,故采用其成员变量aPps来记录该intent绑定的所有client进程, 其数据类型如下:

ArrayMap<ProcessRecord, AppBindRecord> apps

(2)binder: service发布过程,调用publishServiceLocked()来赋值的IBinder对象;也就是bindService后的onBinder()方法 的返回值(作target进程的binder服务)的代理对象。简单来说就是onServiceConnected()的第二个参数。

(3)received:

  • 当执行完publishServiceLocked(), 则received=true; requested=true;
  • 当执行killServicesLocked(), 则received=false; requested=false;

2.3 AppBindRecord

功能:一个service与其所关联的client进程

其成员变量connections记录所有的连接信息;

2.4 ConnectionRecord

功能:记录一个service的绑定信息binding; 只有bindService()才会创建该对象。

  1. conn:client进程中的LoadedApk.ServiceDispatcher.InnerConnection的Bp端
  2. activity:不为空,代表发起方拥有activity上下文
  3. clientIntent: 记录如何启动client

执行bindService()便会创建ConnectionRecord对象, 该对象创建后添加到以下对象的列表:

  • ServiceRecord.connections: 记录在ServiceRecord的成员变量;
  • ActiveServices.mServiceConnections: 效果同上;
  • AppBindRecord.connections: 某个service的所有绑定信息会记录在该对象;
  • ProcessRecord.connections: 记录在service所对应的client进程
  • ActivityRecord.connections: 当bindService()过程是由activity context所启动, 则会添加到该对表;否则跳过;

当bindService过程中指定参数flags Context.BIND_AUTO_CREATE, 则会在bind过程创建service;

2.5 LoadedApk

loaded_apk

LoadedApk对象,往往运行在client进程,通过其成员变量mServices来记录相关的service信息。不同的Context下,对于同一个 ServiceConnection会对应唯一的LoadedApk.ServiceDispatcher对象。ServiceDispatcher用于服务分发,即服务连接或死亡事件的派发。

bindService过程并不是直接把ServiceConnection(只是Interface)传递到AMS,而是创建一个InnerConnection(Binder对象)再传递到AMS,这样便于跨进程间交互。

三. Service综述

3.1 启动与销毁

对Service的主要操作如下四个方法:

startService(Intent service)
stopService(Intent service)
bindService(Intent service, ServiceConnection conn, int flags)
unbindService(ServiceConnection conn)

其中:

public interface ServiceConnection {
    public void onServiceConnected(ComponentName name, IBinder service);
    public void onServiceDisconnected(ComponentName name);
}

Service的启动方式主要有startService和bindService的方式. 说明:在这里把执行启动这个动作的一方称为client, 把被启动的陈伟target service.

(1) startService方式:

  • client通过startService()启动target服务;
  • target通过覆写onStartCommand可以执行具体的业务逻辑;
  • client通过stopService()或者service自身通过stopself()来结束服务;
    • 如果存在多个client启动同一个service, 只需一个client便可以stop该服务;

(2) bindService方式:

  • client通过bindService()启动target服务;
  • target通过覆写onBinder将其IBinder对象将其返回给client端;
    • client端通过ServiceConnection的onServiceConnected获取IBinder的代理对象, 便可通过Binder IPC直接操作service的相应业务方法;
  • client通过unbindService()来结束服务的连接关系;
    • 多次bind,则需要等量的unbind操作;

(3) unbindService

前面介绍的bindService()过程会创建与bind服务,对于unbindService则正好是逆过程unbind和摧毁service。

unbindService(ServiceConnection conn)

说明:

  1. unbindService()过程在client进程是对同一个ServiceConnection的bind来执行unbind操作, 从该方法参数也能印证其功能;这里需要注意当采用同一个ServiceConnection执行了bind操作,只需一次unbind就把所有 使用同一个ServiceConnection的bind都一并执行了unbind操作;
  2. 站在AMS角度来看,unbindService(),只有当某个service Intent的IntentBindRecord.apps的个数为0时才执行unbind操作。 也就是说当存在多个进程采用同一个intent bind某个service,那么必须等到所有的进程都执行了unbind操作,才能真正unbind。
  3. 当service是通过startService方式所启动,那么必须通过stopService或者stopSelf()才能destroy该服务,任何的unbindService 是无法destroy该服务;
  4. 当servce时通过bindService带有flags Context.BIND_AUTO_CREATE方式启动的,那么unbind过程会判断如果该service的其他ConnectionRecord都不存在设置BIND_AUTO_CREATE,则会直接destroy该service;如果存在一个,则不会destroy。可见,决定是否destroy service的过程,是否存在其他的不带BIND_AUTO_CREATE的bind service完全忽略。

3.2 生命周期

3.2.1 startService

startService的生命周期:

  • onCreate
  • onStartCommand
  • onDestroy

启动流程图, 点击查看大图

service_lifeline

3.2.2 bindService

bindService的生命周期:

  • onCreate
  • onBind
  • onUnbind
  • onDestroy

启动流程图, 点击查看大图

bind_service

说明:

  1. 图中蓝色代表的是Client进程(发起端), 红色代表的是system_server进程, 黄色代表的是target进程(service所在进程);
  2. Client进程: 通过getServiceDispatcher获取Client进程的匿名Binder服务端,即LoadedApk.ServiceDispatcher.InnerConnection,该对象继承于IServiceConnection.Stub; 再通过bindService调用到system_server进程;
  3. system_server进程: 依次通过scheduleCreateService和scheduleBindService方法, 远程调用到target进程; 4: target进程: 依次执行onCreate()和onBind()方法; 将onBind()方法的返回值IBinder(作为target进程的binder服务端)通过publishService传递到system_server进程;
  4. system_server进程: 利用IServiceConnection代理对象向Client进程发起connected()调用, 并把target进程的onBind返回Binder对象的代理端传递到Client进程;
  5. Client进程: 回调到onServiceConnection()方法, 该方法的第二个参数便是target进程的binder代理端. 到此便成功地拿到了target进程的代理, 可以畅通无阻地进行交互.

另外,说明bindService过程中只有指定参数flags Context.BIND_AUTO_CREATE, 才会在bind过程创建/销毁service,即BringUpServiceLocked和bringDownServiceIfNeededLocked过程;

3.3 Foreground

在系统内存资源不足的情况下,会优先杀掉低优先级的进程。对于只有service的进程,有些情况对于用户来说是可感知的app。往往不希望被系统所杀,比如正在听音乐。系统默认service都是后台的,可以通过startForeground()把该service提升到foreground优先级,那么adj便会成为PERCEPTIBLE_APP_ADJ(可感知的级别),这个级别的app一般不会轻易被杀。当用户不再听歌时,应该主动调用stopForeground(),将其优先级还原到后台,为用户提供更好的体验,相关API位于文件Service.java :

startForeground(int id, Notification notification)
stopForeground(boolean removeNotification)

以上两个方法进入AMS都是调用setServiceForeground();对于startForeground(),往往通过postNotification()来展示 一个通知;对于stopForeground(),当removeNotification=true,则通过 cancelNotification()来取消通知。

作为前台service,必须要有一个status bar的通知,并且通知不会消失直到service停止或许主动移除前台优先级。

四大组件之BroadcastRecord

$
0
0

一. 引言

广播在Android系统使用频率比较高,广播的使用场景往往是在满足某种条件下发出一个事件(broadcast), 多处(Receiver)可以监听该事件通知并做出相应的改变。比如亮/灭屏,网络状态切换等事件发送时都会发出相应的广播。

LoadedApk
    ReceiverDispatcher
        InnerReceiver extends IIntentReceiver.Stub
        Args extends BroadcastReceiver.PendingResult implements Runnable

    ServiceDispatcher
        InnerConnection extends IServiceConnection.Stub
        RunConnection implements Runnable

关系:

  • InnerReceiver与ReceiverDispatcher在数量上一一对应;
  • InnerConnection与ServiceDispatcher在数量上也一一对应;

二. Broadcast数据结构

点击查看大图

broadcast_record

2.1 BroadcastRecord

  1. callerApp:广播发送者的进程;
  2. ordered:是否有序广播;
  3. sticky:是否粘性广播;
  4. receivers:广播接收器,包括动态注册(BroadcastFilter)和静态注册(ResolveInfo);
  5. 时间点:
    • enqueueClockTime: 广播入队列时间点;
    • dispatchTime:广播分发时间点;
    • receiverTime:当前receiver开始处理时间点;
    • finishTime:广播处理完成时间点;

2.2 BroadcastFilter

只有registerReceiver()过程才会创建BroadcastFilter,也就是该对象用于动态注册的广播Receiver; BroadcastFilter继承于IntentFilter.

  • packageName:发起注册广播接收器所对应的包名;
  • owningUid:广播接收器所对应的uid;

2.3 ReceiverList

同样地, 只有registerReceiver()过程才会创建ReceiverList;

2.4 AMS

点击查看大图

broadcast_relation1

  • mRegisteredReceivers:类型为HashMap, 其key数据类型为客户端InnerReceiver的Binder Bp端,value为ReceiverList(广播接收者列表);
    • ReceiverList是一个BroadcastFilter列表;
  • mFgBroadcastQueue/mBgBroadcastQueue:分别代表前后台广播队列;
    • 每个队列里面有包含mOrderedBroadcasts/mParallelBroadcasts(串行和并行广播列表);
    • 其中每个广播BroadcastRecord里面有一个receivers,记录当前广播的所有接收者,包含BroadcastFilter和ResolveInfo;

也就是说AMS记录的前/后台广播队列和已注册的广播接收者(mRegisteredReceivers)都有对应的相同BroadcastFilter;

2.5 BroadcastQueue

  1. mBroadcastsScheduled为true,代表当前已广播消息BROADCAST_INTENT_MSG, 正在等待处理中.
  2. 并行广播队列,只有动态注册的receiver;串行广播队列,可能同时又动态注册和静态注册的receiver;

三. 过程简述

广播分为注册过程和发送过程

3.1 注册过程

动态广播

App进程通过registerReceiver()向system_server进程注册BroadcastReceiver。这个过程会将App进程的两个binder 服务对象传递给system_server进程:

  • ApplicationThread: 继承于ApplicationThreadNative, 作为ActivityThread的成员变量mAppThread;
  • InnerReceiver: 继承于IIntentReceiver.Stub,作为LoadedApk.ReceiverDispatcher的成员变量mIIntentReceiver

这里有一个ReceiverDispatcher(广播分发者), 其个数跟BroadcastReceiver是一一对象的。每个广播接收者对应一个广播分发者, 当AMS向app发送广播时会调用到app进程的广播分发者,然后再将广播以message形式post到app的主线程,来执行onReceive().

静态广播

通过AndroidManifest.xml声明receiver,在系统开机过程通过PKMS来解析所有的静态广播接收者。

PKMS中有一个成员变量mReceivers,其数据类型为ActivityIntentResolver;可通过PKMS的 queryIntentReceivers()方法来查询指定Intent所对应的ResolveInfo列表。

3.2 发送过程

点击查看大图seq_broadcast

处理过程,根据注册方式不同执行流程略有不同。

  • 根据发送的广播Intent是否带有Intent.FLAG_RECEIVER_FOREGROUND, 来决定将广播放入AMS中的前台广播队列(mFgBroadcastQueue) ,还是后台广播队列(mBgBroadcastQueue).
  • 发送广播的过程, 也就是将BROADCAST_INTENT_MSG消息发送到ActivityManager线程即可返回.
  • 静态注册的receiver,一定是按照order方式处理;
  • 动态注册的receiver,则需要根据发送方式order来决定处理方式;即可能并行队列, 也可以在串行队列
  • 位于mParallelBroadcasts中的并行广播, 一次性全部发出.
  • 位于mOrderedBroadcasts中的串行广播,一次处理一个,等待上一个receive完成才继续处理;

更多源码详细过程,见Android Broadcast广播机制分析


四大组件之ContentProviderRecord

$
0
0

一. 引言

作为四大组件之一的ContentProvider,相比来说是设计得稍逊色,有些地方不太合理,比如provider级联被杀, 请求provider时占用system_server的binder线程来wait()等。

即便很少自定义ContentProvider,但你也可以会需要使用到ContentProvider,比如通信录,Settings等; 使用Provider往往跟数据库结合起来使用,所以这里需要注意不要再主线程用provider做过多的io操作。

二. ContentProvider数据结构

先以一幅图来展示AMS管理ContentProvider所涉及的相关数据结构: 点击查看大图

content_provider_record

2.1 ContentProviderRecord

  • provider:在ActivityThread的installProvider()过程,会创建ContentProvider对象, 该对象有一个成员变量Transport,继承于ContentProviderNative对象,作为binder服务端。经过binder传递到system_server 进程的便是ContentProvider.Transport的binder代理对象, 由publishContentProviders()过程完成赋值;
  • proc:记录provider所在的进程,是在publishContentProviders()过程完成赋值;
  • launchingApp:记录等待provider所在进程启动,getContentProviderImpl()过程执行创建进程之后赋值;
  • connections:记录该ContentProvider的所有连接信息,
    • 添加连接过程:incProviderCountLocked
    • 减少连接过程:decProviderCountLocked,removeDyingProviderLocked,cleanUpApplicationRecordLocked;

2.2 ContentProviderConnection

功能:连接contentProvider与请求该provider所对应的进程

  1. provider:目标provider所对应的ContentProviderRecord结构体;
  2. client:请求该provider的客户端进程;
  3. waiting:该连接的client进程正在等待该provider发布

2.3 ProcessRecord

  • pubProviders: ArrayMap<String, ContentProviderRecord>
    • 记录当前进程所有已发布的provider;
  • conProviders: ArrayList
    • 记录当前进程跟其他进程provider所建立的连接

2.4 AMS

  • mProviderMap记录系统所有的provider信息;
  • mLaunchingProviders记录当前正在启动的provider;

2.5 ActivityThread

  • mProviderMap: 记录App端的所有provider信息;
  • mProviderRefCountMap:记录App端的所有provider引用信息;

三. Provider使用过程

点击查看大图

Seq_provider

更多源码详细过程,见理解ContentProvider原理

全面剖析SharedPreferences

$
0
0

一. 概述

SharedPreferences(简称SP)是Android中很常用的数据存储方式,SP采用key-value(键值对)形式, 主要用于轻量级的数据存储, 尤其适合保存应用的配置参数, 但不建议使用SP 来存储大规模的数据, 可能会降低性能.

SP采用xml文件格式来保存数据, 该文件所在目录位于/data/data//shared_prefs/

1.1 使用示例

SharedPreferences sharedPreferences = getSharedPreferences("gityuan", Context.MODE_PRIVATE);

Editor editor = sharedPreferences.edit();
editor.putString("blog", "www.gityuan.com");
editor.putInt("years", 3);
editor.commit();

生成的gityuan.xml文件内容如下:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?><map><stringname="blog">"www.gityuan.com</string><intname="years"value="3"/></map>

1.2 数据结构说明

shared_preference

shared_preference

SharedPreferences与Editor只是两个接口. SharedPreferencesImpl和EditorImpl分别实现了对应接口. 另外, ContextImpl记录着SharedPreferences的重要数据, 如下:

  • sSharedPrefsCache:以包名为key, 二级key是以SP文件, 以SharedPreferencesImpl为value的嵌套map结构
  • mSharedPrefsPaths:记录所有的SP文件, 以文件名为key, 具体文件为value的map结构;
  • mPreferencesDir:是指SP所在目录, 是指/data/data//shared_prefs/

一次数据修改到提交的流程: 先写入到EditorImpl.mModified, 经过commit更新到SharedPreferencesImpl的mMap, 然后再保存到MemoryCommitResult的mapToWriteToDisk, 最后提交到磁盘文件.

二. SharedPreferences

2.1 获取方式

2.1.1 getPreferences

[-> Activity.java]

public SharedPreferences getPreferences(int mode) {
    //[见下文]
    return getSharedPreferences(getLocalClassName(), mode);
}

Activity.getPreferences(mode): 以当前Activity的类名作为SP的文件名. 即xxxActivity.xml.

2.1.2 getDefaultSharedPreferences

[-> PreferenceManager.java]

public static SharedPreferences getDefaultSharedPreferences(Context context) {
    //[见下文]
    return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
           getDefaultSharedPreferencesMode());
}

PreferenceManager.getDefaultSharedPreferences(Context): 以包名加上_preferences作为文件名, 以MODE_PRIVATE模式创建SP文件. 即packgeName_preferences.xml.

2.1.3 getSharedPreferences

当然也可以直接调用Context.getSharedPreferences(name, mode), 以上所有的方法最终都是调用到如下方法:

[-> ContextImpl.java]

class ContextImpl extends Context {
    private ArrayMap<String, File> mSharedPrefsPaths;

    public SharedPreferences getSharedPreferences(String name, int mode) {
        File file;
        synchronized (ContextImpl.class) {
            if (mSharedPrefsPaths == null) {
                mSharedPrefsPaths = new ArrayMap<>();
            }
            //先从mSharedPrefsPaths查询是否存在相应文件
            file = mSharedPrefsPaths.get(name);
            if (file == null) {
                //如果文件不存在, 则创建新的文件 [见小节2.1.4]
                file = getSharedPreferencesPath(name);
                mSharedPrefsPaths.put(name, file);
            }
        }
        //[见小节2.2]
        return getSharedPreferences(file, mode);
    }
}

2.1.4 getSharedPreferencesPath

[-> ContextImpl.java]

public File getSharedPreferencesPath(String name) {
    return makeFilename(getPreferencesDir(), name + ".xml");
}

private File getPreferencesDir() {
    synchronized (mSync) {
        if (mPreferencesDir == null) {
            //创建目录/data/data/package name/shared_prefs/
            mPreferencesDir = new File(getDataDir(), "shared_prefs");
        }
        return ensurePrivateDirExists(mPreferencesDir);
    }
} 流程说明:
  1. 先从mSharedPrefsPaths查询是否存在相应文件;
  2. 如果文件不存在, 则创建新的xml文件; 如果目录也不存在, 则先创建目录创建目录/data/data/package name/shared_prefs/
  3. 其中mSharedPrefsPaths用于记录所有的SP文件, 是以文件名为key的Map数据结构.

2.2 getSharedPreferences

[-> ContextImpl.java]

public SharedPreferences getSharedPreferences(File file, int mode) {
    checkMode(mode); //[见小节2.2.1]
    SharedPreferencesImpl sp;
    synchronized (ContextImpl.class) {
        //[见小节2.2.2]
        final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
        sp = cache.get(file);
        if (sp == null) {
            //创建SharedPreferencesImpl[见小节2.3]
            sp = new SharedPreferencesImpl(file, mode);
            cache.put(file, sp);
            return sp;
        }
    }

    //指定多进程模式, 则当文件被其他进程改变时,则会重新加载
    if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
        getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
        sp.startReloadIfChangedUnexpectedly();
    }
    return sp;
}

2.2.1 checkMode

[-> ContextImpl.java]

private void checkMode(int mode) {
    if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.N) {
        if ((mode & MODE_WORLD_READABLE) != 0) {
            throw new SecurityException("MODE_WORLD_READABLE no longer supported");
        }
        if ((mode & MODE_WORLD_WRITEABLE) != 0) {
            throw new SecurityException("MODE_WORLD_WRITEABLE no longer supported");
        }
    }
}

从Android N开始, 创建的SP文件模式, 不允许MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE模块, 否则会直接抛出异常SecurityException. 另外, 顺带说一下MODE_MULTI_PROCESS这种多进程的方式也是Google不推荐的方式, 后续同样会不再支持, 强烈建议App不用使用该方式来实现多个进程实现 同一个SP文件.

当设置MODE_MULTI_PROCESS模式, 则每次getSharedPreferences过程, 会检查SP文件上次修改时间和文件大小, 一旦所有修改则会重新从磁盘加载文件.

2.2.2 getSharedPreferencesCacheLocked

[-> ContextImpl.java]

private ArrayMap<File, SharedPreferencesImpl> getSharedPreferencesCacheLocked() {
    if (sSharedPrefsCache == null) {
        sSharedPrefsCache = new ArrayMap<>();
    }

    final String packageName = getPackageName();
    ArrayMap<File, SharedPreferencesImpl> packagePrefs = sSharedPrefsCache.get(packageName);
    if (packagePrefs == null) {
        packagePrefs = new ArrayMap<>();
        sSharedPrefsCache.put(packageName, packagePrefs);
    }
    return packagePrefs;
}

2.3 SharedPreferencesImpl初始化

[-> SharedPreferencesImpl.java]

SharedPreferencesImpl(File file, int mode) {
    mFile = file;
    //创建为.bak为后缀的备份文件
    mBackupFile = makeBackupFile(file);
    mMode = mode;
    mLoaded = false;
    mMap = null;
    startLoadFromDisk(); //[见小节2.3.1]
}

同名的.bak备份文件用于发生异常时, 可通过备份文件来恢复数据.

2.3.1 startLoadFromDisk

[-> SharedPreferencesImpl.java]

private void startLoadFromDisk() {
    synchronized (this) {
        mLoaded = false;
    }
    new Thread("SharedPreferencesImpl-load") {
        public void run() {
            loadFromDisk(); //[见小节2.3.2]
        }
    }.start();
}

mLoaded用于标记SP文件已加载到内存. 创建线程去实现从磁盘加载sp文件的工作.

2.3.2 loadFromDisk

[-> SharedPreferencesImpl.java]

private void loadFromDisk() {
    synchronized (SharedPreferencesImpl.this) {
        if (mLoaded) {
            return;
        }
        if (mBackupFile.exists()) {
            mFile.delete();
            mBackupFile.renameTo(mFile);
        }
    }

    Map map = null;
    StructStat stat = null;
    try {
        stat = Os.stat(mFile.getPath());
        if (mFile.canRead()) {
            BufferedInputStream str = null;
            try {
                str = new BufferedInputStream(new FileInputStream(mFile), 16*1024);
                map = XmlUtils.readMapXml(str);
            } catch (XmlPullParserException | IOException e) {
                ...
            } finally {
                IoUtils.closeQuietly(str);
            }
        }
    } catch (ErrnoException e) {
        ...
    }

    synchronized (SharedPreferencesImpl.this) {
        mLoaded = true;
        if (map != null) {
            mMap = map; //从文件读取的信息保存到mMap
            mStatTimestamp = stat.st_mtime; //更新修改时间
            mStatSize = stat.st_size; //更新文件大小
        } else {
            mMap = new HashMap<>();
        }
        notifyAll(); //唤醒处于等待状态的线程
    }
}

整个获取SharedPreferences简单总结:

  • 首次使用则创建相应xml文件;
  • 异步加载文件内容到内存; 此时执行getXXX()和setxxx()以及edit()方法都是阻塞等待的, 直到文件数据全部加载到内存;
  • 一旦完全加载到内存, 后续的getXXX()则是直接访问内存.

2.4 查询数据

2.4.1 getString

[-> SharedPreferencesImpl.java]

public String getString(String key, @Nullable String defValue) {
    synchronized (this) {
        //检查是否加载完成[见小节2.4.2]
        awaitLoadedLocked();
        String v = (String)mMap.get(key);
        return v != null ? v : defValue;
    }
}
  • 当loadFromDisk没有执行完成, 则会阻塞查询操作;
  • 当数据加载完成, 则直接从mMap来查询相应数据;

2.4.2 awaitLoadedLocked

[-> SharedPreferencesImpl.java]

private void awaitLoadedLocked() {
    if (!mLoaded) {
        BlockGuard.getThreadPolicy().onReadFromDisk();
    }
    while (!mLoaded) {
        try {
            wait(); //当没有加载完成,则进入等待状态
        } catch (InterruptedException unused) {
        }
    }
}

三. Editor

### 3.1 edit [-> SharedPreferencesImpl.java]

public Editor edit() {
    synchronized (this) {
        awaitLoadedLocked(); //[见小节2.4.2]
    }

    return new EditorImpl(); //创建EditorImpl
}

该过程同样要等待awaitLoadedLocked完成, 然后创建EditorImpl对象. 而EditorImpl作为SharedPreferencesImpl的内部类,其继承于Editor类.

3.2 EditorImpl

[-> SharedPreferencesImpl.java:: EditorImpl]

public final class EditorImpl implements Editor {
    private final Map<String, Object> mModified = Maps.newHashMap();
    private boolean mClear = false;

    //插入数据
    public Editor putString(String key, @Nullable String value) {
        synchronized (this) {
            //插入数据, 先暂存到mModified对象
            mModified.put(key, value);
            return this;
        }
    }
    //移除数据
    public Editor remove(String key) {
        synchronized (this) {
            mModified.put(key, this);
            return this;
        }
    }

    //清空全部数据
    public Editor clear() {
        synchronized (this) {
            mClear = true;
            return this;
        }
    }
}

从这里可以看出, 这些数据修改操作仅仅是修改mModified和mClear. 直到数据提交commit或许apply过程, 才会真正的把数据更新到SharedPreferencesImpl(简称SPI). 比如设置mClear=true则会情况SPI的mMap数据.

四. 数据提交

这里重点来说说数据提交的两个重要方法commit()和apply().

4.1 commit

[-> SharedPreferencesImpl.java:: EditorImpl]

public boolean commit() {
    //将数据更新到内存[见小节4.2]
    MemoryCommitResult mcr = commitToMemory();
    //将内存数据同步到文件[见小节4.3]
    SharedPreferencesImpl.this.enqueueDiskWrite(mcr, null);
    try {
        //进入等待状态, 直到写入文件的操作完成
        mcr.writtenToDiskLatch.await();
    } catch (InterruptedException e) {
        return false;
    }
    //通知监听则, 并在主线程回调onSharedPreferenceChanged()方法
    notifyListeners(mcr);
    // 返回文件操作的结果数据
    return mcr.writeToDiskResult;
}

4.2 commitToMemory

[-> SharedPreferencesImpl.java:: EditorImpl]

private MemoryCommitResult commitToMemory() {
    MemoryCommitResult mcr = new MemoryCommitResult();
    synchronized (SharedPreferencesImpl.this) {
        if (mDiskWritesInFlight > 0) {
            mMap = new HashMap<String, Object>(mMap);
        }
        mcr.mapToWriteToDisk = mMap;
        mDiskWritesInFlight++;

        //是否有监听key改变的监听者
        boolean hasListeners = mListeners.size() > 0;
        if (hasListeners) {
            mcr.keysModified = new ArrayList<String>();
            mcr.listeners = new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
        }

        synchronized (this) {
            //当mClear为true, 则直接清空mMap
            if (mClear) {
                if (!mMap.isEmpty()) {
                    mcr.changesMade = true;
                    mMap.clear();
                }
                mClear = false;
            }

            for (Map.Entry<String, Object> e : mModified.entrySet()) {
                String k = e.getKey();
                Object v = e.getValue();
                //注意此处的this是个特殊值, 用于移除相应的key操作.
                if (v == this || v == null) {
                    if (!mMap.containsKey(k)) {
                        continue;
                    }
                    mMap.remove(k);
                } else {
                    if (mMap.containsKey(k)) {
                        Object existingValue = mMap.get(k);
                        if (existingValue != null && existingValue.equals(v)) {
                            continue;
                        }
                    }
                    mMap.put(k, v);
                }

                mcr.changesMade = true; // changesMade代表数据是否有改变
                if (hasListeners) {
                    mcr.keysModified.add(k); //记录发生改变的key
                }
            }
            mModified.clear(); //清空EditorImpl中的mModified数据
        }
    }
    return mcr;
}

该方法的主要功能: 把EditorImpl数据更新到SPI.

  • 将mMap信息赋值给mapToWriteToDisk, 并mDiskWritesInFlight加1;
  • 当mClear为true, 则直接清空mMap;
  • 当value值为this或null, 则移除相应的key;
  • 当value值发生改变, 则会更新到mMap;

只要有key/value发生改变(新增, 删除), 则设置mcr.changesMade = true. 最后会清空EditorImpl中的mModified数据.

4.3 enqueueDiskWrite

[-> SharedPreferencesImpl.java]

private void enqueueDiskWrite(final MemoryCommitResult mcr,
                              final Runnable postWriteRunnable) {
    final Runnable writeToDiskRunnable = new Runnable() {
            public void run() {
                synchronized (mWritingToDiskLock) {
                    //执行文件写入操作[见小节4.3.1]
                    writeToFile(mcr);
                }
                synchronized (SharedPreferencesImpl.this) {
                    mDiskWritesInFlight--;
                }
                //此时postWriteRunnable为null不执行该方法
                if (postWriteRunnable != null) {
                    postWriteRunnable.run();
                }
            }
        };

    final boolean isFromSyncCommit = (postWriteRunnable == null);

    if (isFromSyncCommit) { //commit方法会进入该分支
        boolean wasEmpty = false;
        synchronized (SharedPreferencesImpl.this) {
            //commitToMemory过程会加1,则wasEmpty=true
            wasEmpty = mDiskWritesInFlight == 1;
        }
        if (wasEmpty) {
            //跳转到上面
            writeToDiskRunnable.run();
            return;
        }
    }
    //不执行该方法
    QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}

4.3.1 writeToFile

private void writeToFile(MemoryCommitResult mcr) {
    if (mFile.exists()) {
        if (!mcr.changesMade) { //没有key发生改变, 则直接返回
            mcr.setDiskWriteResult(true);
            return;
        }
        if (!mBackupFile.exists()) {
            //当备份文件不存在, 则把mFile重命名为备份文件
            if (!mFile.renameTo(mBackupFile)) {
                mcr.setDiskWriteResult(false);
                return;
            }
        } else {
            mFile.delete(); //否则,直接删除mFile
        }
    }

    try {
        FileOutputStream str = createFileOutputStream(mFile);
        if (str == null) {
            mcr.setDiskWriteResult(false);
            return;
        }
        //将mMap全部信息写入文件
        XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
        FileUtils.sync(str);
        str.close();
        ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
        try {
            final StructStat stat = Os.stat(mFile.getPath());
            synchronized (this) {
                mStatTimestamp = stat.st_mtime;
                mStatSize = stat.st_size;
            }
        } catch (ErrnoException e) {
            ...
        }
        //写入成功, 则删除备份文件
        mBackupFile.delete();
        //返回写入成功, 唤醒等待线程
        mcr.setDiskWriteResult(true);
        return;
    } catch (XmlPullParserException e) {
        ...
    } catch (IOException e) {
        ...
    }
    //如果写入文件的操作失败, 则删除未成功写入的文件
    if (mFile.exists()) {
        if (!mFile.delete()) {
            ...
        }
    }
    //返回写入失败, 唤醒等待线程
    mcr.setDiskWriteResult(false);
}

该方法的主要功能:

  1. 当没有key发生改变, 则直接返回; 否则执行step2;
  2. 将mMap全部信息写入文件, 如果写入成功则删除备份文件,如果写入失败则删除mFile.

可见, 每次commit是把全部数据更新到文件, 所以每个文件的数据量必须保证足够精简. 再来看看apply过程.

4.4 apply

[-> SharedPreferencesImpl.java:: EditorImpl]

public void apply() {
    //把数据更新到内存[见小节4.2]
    final MemoryCommitResult mcr = commitToMemory();
    final Runnable awaitCommit = new Runnable() {
            public void run() {
                try {
                    //进入等待状态
                    mcr.writtenToDiskLatch.await();
                } catch (InterruptedException ignored) {
                }
            }
        };

    //将awaitCommit添加到QueuedWork
    QueuedWork.add(awaitCommit);

    Runnable postWriteRunnable = new Runnable() {
            public void run() {
                awaitCommit.run();
                //从QueuedWork移除
                QueuedWork.remove(awaitCommit);
            }
        };

    //[见小节4.4.1]
    SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
    notifyListeners(mcr);
}

4.4.1 enqueueDiskWrite

[-> SharedPreferencesImpl.java]

private void enqueueDiskWrite(final MemoryCommitResult mcr,
                              final Runnable postWriteRunnable) {
    final Runnable writeToDiskRunnable = new Runnable() {
            public void run() {
                synchronized (mWritingToDiskLock) {
                    //执行文件写入操作[见小节4.3.1]
                    writeToFile(mcr);
                }
                synchronized (SharedPreferencesImpl.this) {
                    mDiskWritesInFlight--;
                }

                if (postWriteRunnable != null) {
                    postWriteRunnable.run();
                }
            }
        };

    final boolean isFromSyncCommit = (postWriteRunnable == null);
    if (isFromSyncCommit) {
        ... //postWriteRunnable不为空
    }
    //将任务放入单线程的线程池来执行
    QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}

4.4.2 QueuedWork

[-> QueuedWork.java]

public class QueuedWork {

    private static final ConcurrentLinkedQueue<Runnable> sPendingWorkFinishers =
       new ConcurrentLinkedQueue<Runnable>();

    public static void add(Runnable finisher) {
        sPendingWorkFinishers.add(finisher);
    }

    public static void remove(Runnable finisher) {
        sPendingWorkFinishers.remove(finisher);
    }

    public static void waitToFinish() {
        Runnable toFinish;
        while ((toFinish = sPendingWorkFinishers.poll()) != null) {
            toFinish.run();
        }
    }

    public static boolean hasPendingWork() {
        return !sPendingWorkFinishers.isEmpty();
    }
}

可见, apply跟commit的最大区别 在于apply的写入文件操作是在单线程的线程池来完成.

  • apply方法开始的时候, 会把awaitCommit放入QueuedWork;
  • 文件写入操作完成, 则会把相应的awaitCommit从QueuedWork中移除.

QueuedWork在这里存在的价值主要是用于在Stop Service, finish BroadcastReceiver过程用于 判定是否处理完所有的异步SP操作.

五. 总结

apply 与commit的对比

  • apply没有返回值, commit有返回值能知道修改是否提交成功
  • apply是将修改提交到内存,再异步提交到磁盘文件; commit是同步的提交到磁盘文件;
  • 多并发的提交commit时,需等待正在处理的commit数据更新到磁盘文件后才会继续往下执行,从而降低效率; 而apply只是原子更新到内存,后调用apply函数会直接覆盖前面内存数据,从一定程度上提高很多效率。

优化建议:

  • 强烈建议不要在sp里面存储特别大的key/value, 有助于减少卡顿/anr
  • 请不要高频地使用apply, 尽可能地批量提交
  • commit直接在主线程操作, 更要注意了
  • 不要使用MODE_MULTI_PROCESS
  • 高频操作的key与低频率操作的, 可以适当考虑分开存放不同文件.
  • 不要一上来就执行getSharedPreferences().edit(), 应该分成两大步骤来做.
  • 不要连续多次edit(), 应该获取一次获取edit(),然后多次执行putxxx(), 减少内存波动; 经常看到大家喜欢封装方法, 结果就导致这种情况的出现.
  • 每次commit时会把全部的数据更新的文件, 所以整个文件是不应该过大的, 影响整体性能;

LocalBroadcastManager原理分析

$
0
0

一. 概述

当不需要通过send broadcasts来完成跨应用的通信,那么建议采用LocalBroadcastManager, 将会是更加地高效、安全地方式,并且对系统带来的影响也是更小。

  • BroadcastReceiver采用的binder方式实现跨进程间的通信;
  • LocalBroadcastManager使用Handler通信机制。

1.1 使用实例

//1. 自定义广播接收者
public class LocalReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        ...
    }
}
LocalReceiver localReceiver = new LocalReceiver();

//2. 注册广播
LocalBroadcastManager.getInstance(context)
             .registerReceiver(localReceiver, new IntentFilter(“gityuan”));
//4. 发送广播
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("gityuan"));
//5. 取消注册广播
LocalBroadcastManager.getInstance(context).unregisterReceiver(localReceiver);

LocalBroadcastManager注册只能通过代码注册方式,而不能通过xml中注册静态广播,本地广播并不会跨进程通信,不用 跟system_server交互,即可完成广播全过程。

二. 原理分析

2.1 LocalBroadcastManager

[-> LocalBroadcastManager.java]

public final class LocalBroadcastManager {
    public static LocalBroadcastManager getInstance(Context context) {
        synchronized (mLock) {
            if (mInstance == null) {
                //单例模式,创建LocalBroadcastManager对象
                mInstance = new LocalBroadcastManager(context.getApplicationContext());
            }
            return mInstance;
        }
    }

    private LocalBroadcastManager(Context context) {
        mAppContext = context;
        //创建运行在主线程的Handler
        mHandler = new Handler(context.getMainLooper()) {

            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_EXEC_PENDING_BROADCASTS:
                        executePendingBroadcasts();
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        };
    }
}

2.2 registerReceiver

public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    synchronized (mReceivers) {
        //创建ReceiverRecord对象
        ReceiverRecord entry = new ReceiverRecord(filter, receiver);
        //查询或创建数据到mReceivers
        ArrayList<IntentFilter> filters = mReceivers.get(receiver);
        if (filters == null) {
            filters = new ArrayList<IntentFilter>(1);
            mReceivers.put(receiver, filters);
        }
        filters.add(filter);
        //查询或创建数据到mActions
        for (int i=0; i<filter.countActions(); i++) {
            String action = filter.getAction(i);
            ArrayList<ReceiverRecord> entries = mActions.get(action);
            if (entries == null) {
                entries = new ArrayList<ReceiverRecord>(1);
                mActions.put(action, entries);
            }
            entries.add(entry);
        }
    }
}

注册过程,主要是向mReceivers和mActions添加相应数据:

  • mReceivers:数据类型为HashMap<BroadcastReceiver, ArrayList>, 记录广播接收者与IntentFilter列表的对应关系;
  • mActions:数据类型为HashMap<String, ArrayList>, 记录action与广播接收者的对应关系。

2.3 sendBroadcast

public boolean sendBroadcast(Intent intent) {
    synchronized (mReceivers) {
        final String action = intent.getAction();
        final String type = intent.resolveTypeIfNeeded(
                mAppContext.getContentResolver());
        final Uri data = intent.getData();
        final String scheme = intent.getScheme();
        final Set<String> categories = intent.getCategories();
        //根据Intent的action来查询相应的广播接收者列表
        ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
        if (entries != null) {
            ArrayList<ReceiverRecord> receivers = null;
            for (int i=0; i<entries.size(); i++) {
                ReceiverRecord receiver = entries.get(i);
                if (receiver.broadcasting) {
                    continue; //正在处理广播的receiver,则跳过
                }

                int match = receiver.filter.match(action, type, scheme, data,
                        categories, "LocalBroadcastManager");
                if (match >= 0) {
                    if (receivers == null) {
                        receivers = new ArrayList<ReceiverRecord>();
                    }
                    receivers.add(receiver);
                    receiver.broadcasting = true;
                }
            }

            if (receivers != null) {
                for (int i=0; i<receivers.size(); i++) {
                    receivers.get(i).broadcasting = false;
                }
                //创建相应广播,添加到mPendingBroadcasts队列
                mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
                if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
                    //发送消息【见小节2.3.1】
                    mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
                }
                return true;
            }
        }
    }
    return false;
}

主要功能:

  • 根据Intent的action来查询相应的广播接收者列表;
  • 创建相应广播,添加到mPendingBroadcasts队列;
  • 发送MSG_EXEC_PENDING_BROADCASTS消息。

2.3.1 executePendingBroadcasts

private void executePendingBroadcasts() {
    while (true) {
        BroadcastRecord[] brs = null;
        //将mPendingBroadcasts保存到brs数组
        synchronized (mReceivers) {
            final int N = mPendingBroadcasts.size();
            if (N <= 0) {
                return;
            }
            brs = new BroadcastRecord[N];
            mPendingBroadcasts.toArray(brs);
            mPendingBroadcasts.clear();
        }
        //回调相应广播接收者的onReceive方法。
        for (int i=0; i<brs.length; i++) {
            BroadcastRecord br = brs[i];
            for (int j=0; j<br.receivers.size(); j++) {
                br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
            }
        }
    }
}

该过程运行在app进程的主线程,所以onReceive()方法不能有耗时操作。

2.4 unregisterReceiver

public void unregisterReceiver(BroadcastReceiver receiver) {
    synchronized (mReceivers) {
        //从mReceivers移除该广播接收者
        ArrayList<IntentFilter> filters = mReceivers.remove(receiver);
        if (filters == null) {
            return;
        }
        
        //从mActions移除接收者为空的action
        for (int i=0; i<filters.size(); i++) {
            IntentFilter filter = filters.get(i);
            for (int j=0; j<filter.countActions(); j++) {
                String action = filter.getAction(j);
                ArrayList<ReceiverRecord> receivers = mActions.get(action);
                if (receivers != null) {
                    for (int k=0; k<receivers.size(); k++) {
                        if (receivers.get(k).receiver == receiver) {
                            receivers.remove(k);
                            k--;
                        }
                    }
                    if (receivers.size() <= 0) {
                        mActions.remove(action);
                    }
                }
            }
        }
    }
}

三. 总结

广播注册/发送/取消注册过程都使用同步锁mReceivers来保护,从而保证进程内的多线程访问安全。 最后,再来看看使用LocalBroadcastManager的优势:

  • 发送的广播不会离开当前所在的app, 因此不用担心私有隐私数据的泄漏,确保安全性;
  • 其他应用也无法发送这类广播到当前app,则不用担心会暴露漏洞而被其他app所利用;
  • 比系统全局的广播更加高效,且对系统整体性能影响更小;

那么不足是什么呢?LocalBroadcastManager只能用于同一个进程不同线程间通信,而不能跨进程, 即便是同一个apk里面的两个进程也不行,需要使用BroadcastReceiver。

LocalBroadcastManager与BroadcastReceiver使用场景:

  • 同一个进程的多线程间通信,强烈建议使用LocalBroadcastManager;
  • 跨进程的通信,则使用BroadcastReceiver。(当然跨进程实现方式有多种,这里只说广播相关的方案)

四大组件之ActivityRecord

$
0
0

一. 引言

BroadcastRecord,ServiceRecord都继承于Binder对象,而ActivityRecord并没有继承于Binder。 但ActivityRecord的成员变量appToken的数据类型为Token,Token继承于IApplicationToken.Stub。

appToken:system_server进程通过调用scheduleLaunchActivity()将appToken传递到App进程,

  • 调用createActivityContext(),保存到ContextImpl.mActivityToken
  • 调用activity.attach(),保存到Activity.mToken;

ServiceRecord本身继承于Binder对象,传递到客户端的代理:

  • 调用Service.attach(),保存到Service.mToken;
  • 用途:stopSelf,startForeground, stopForeground

二. ActivityRecord结构体

先以一幅图来展示AMS管理Activity所涉及的相关数据结构: 点击查看大图

activity_record

  • ActivityRecord: 记录着Activity信息
  • TaskRecord: 记录着task信息
  • ActivityStack: 栈信息

2.1 ActivityRecord

Activity的信息记录在ActivityRecord对象, 并通过通过成员变量task指向TaskRecord

  • ProcessRecord app //跑在哪个进程
  • TaskRecord task //跑在哪个task
  • ActivityInfo info // Activity信息
  • int mActivityType //Activity类型
  • ActivityState state //Activity状态
  • ApplicationInfo appInfo //跑在哪个app
  • ComponentName realActivity //组件名
  • String packageName //包名
  • String processName //进程名
  • int launchMode //启动模式
  • int userId // 该Activity运行在哪个用户id

再来说一说Activity类型和Activity状态的常量:

mActivityType:

  • APPLICATION_ACTIVITY_TYPE:普通应用类型
  • HOME_ACTIVITY_TYPE:桌面类型
  • RECENTS_ACTIVITY_TYPE:最近任务类型

ActivityState:

  • INITIALIZING
  • RESUMED:已恢复
  • PAUSING
  • PAUSED:已暂停
  • STOPPING
  • STOPPED:已停止
  • FINISHING
  • DESTROYING
  • DESTROYED:已销毁

最后,说一说时间相关的成员变量:

时间点赋值时间含义
createTimenew ActivityRecordActivity首次创建时间点
displayStartTimeAS.setLaunchTimeActivity首次启动时间点
fullyDrawnStartTimeAS.setLaunchTimeActivity首次启动时间点
startTime Activity上次启动的时间点
lastVisibleTimeAR.windowsVisibleLockedActivity上次成为可见的时间点
cpuTimeAtResumeAS.completeResumeLocked从Rsume以来的cpu使用时长
pauseTimeAS.startPausingLockedActivity上次暂停的时间点
launchTickTimeAR.startLaunchTickingLockedEng版本才赋值
lastLaunchTimeASS.realStartActivityLocked上一次启动时间

其中AR是指ActivityRecord, AS是指ActivityStack。

2.2 TaskRecord

Task的信息记录在TaskRecord对象.

  • ActivityStack stack; //当前所属的stack
  • ArrayList mActivities; // 当前task的所有Activity列表
  • int taskId
  • String affinity; 是指root activity的affinity,即该Task中第一个Activity;
  • int mCallingUid;
  • String mCallingPackage; //调用者的包名

2.3 ActivityStack

  • ArrayList mTaskHistory //保存所有的Task列表
  • ArrayList mStacks; //所有stack列表
  • final int mStackId;
  • int mDisplayId;
  • ActivityRecord mPausingActivity //正在pause
  • ActivityRecord mLastPausedActivity
  • ActivityRecord mResumedActivity //已经resumed
  • ActivityRecord mLastStartedActivity

所有前台stack的mResumedActivity的state == RESUMED, 则表示allResumedActivitiesComplete, 此时mLastFocusedStack = mFocusedStack;

2.4 ActivityStackSupervisor

  • ActivityStack mHomeStack //桌面的stack
  • ActivityStack mFocusedStack //当前聚焦stack
  • ActivityStack mLastFocusedStack //正在切换
  • SparseArray mActivityDisplays //displayId为key
  • SparseArray mActivityContainers // mStackId为key

home的栈ID等于0,即HOME_STACK_ID = 0;

三. Activity栈关系

3.1 Stack组成图

Activity栈结构体的组成关系,点击查看大图

ams_relations

  • 一般地,对于没有分屏功能以及虚拟屏的情况下,ActivityStackSupervisor与ActivityDisplay都是系统唯一;
  • ActivityDisplay主要有Home Stack和App Stack这两个栈;
  • 每个ActivityStack中可以有若干个TaskRecord对象;
  • 每个TaskRecord包含如果个ActivityRecord对象;
  • 每个ActivityRecord记录一个Activity信息。

(1)正向关系链表:

ActivityStackSupervisor.mActivityDisplays 
-> ActivityDisplay.mStacks 
-> ActivityStack.mTaskHistory 
-> TaskRecord.mActivities 
-> ActivityRecord

(2)反向关系链表:

ActivityRecord.task 
-> TaskRecord.stack 
-> ActivityStack.mStackSupervisor
-> ActivityStackSupervisor

注:ActivityStack.mDisplayId可找到所对应的ActivityDisplay;

四. 启动过程

Activity启动与停止流程,点击查看大图

Seq_activity

Activity的pause情况:

  • 当Activity A启动到Activity B,则需要pause掉Activity A;
  • 当系统需要进入休眠状态或许shutdown的过程;
  • 当activity需要finish的过程。

Activity的stop情况:

  • 当Activity处于不可见状态,则需要stop该Activity;
  • 为了更好的用户体验,先resume新的Activity,再待进入idle状态(即没有用户操作)再去stop旧的Activity;

更多源码详细过程,见startActivity启动过程分析

四大组件之综述

$
0
0

本文基于Android 6.0的源代码,来分析四大组件的管理者AMS

frameworks/base/services/core/java/com/android/server/am/
  - ActivityManagerService.java
  - ProcessRecord
  - ActivityStackSupervisor.java 
  - ActivityStack.java
  - ActiveServices
  - BroadcastQueue

一. 引言

Android系统内部非常复杂,经层层封装后,app只需要简单的几行代码便可完成任一组件的启动/结束、 生命周期的操作。然而每一次看似简单的操作,背后所有的复杂工作都是交由系统来完成。

组件启动后,首先需要依赖进程,那么就需要先创建进程,系统需要记录每个进程,这便产生了ProcessRecord。 Android中,对于进程的概念被弱化,通过抽象后的四大组件。让开发者几乎感受不到进程的存在。 当应用退出时,进程也并非马上退出,而是成为cache/empty进程,下次该应用再启动的时候,可以不用 再创建进程直接初始化组件即可,提高启动速度。先来说一说进程。

二. 进程管理

Android系统中用于描述进程的数据结构是ProcessRecord对象,AMS便是管理进程的核心模块。四大组件 (Activity,Service, BroadcastReceiver, ContentProvider)定义在AndroidManifest.xml文件, 每一项都可以用属性android:process指定所运行的进程。同一个app可以运行在通过一个进程,也可以运行在多个进程, 甚至多个app可以共享同一个进程。例如:AndroidManifest.xml中定义Service:

<service android:name =".GityuanService"  android:process =":remote">  
    <intent-filter>  
       <action android:name ="com.action.gityuan" />  
    </intent-filter>  
</service>

GityuanService这个服务运行在remote进程。

2.1 进程关系图

以一幅图来展示AMS管理进程的相关成员变量以及ProcessRecord对象:

点击查看大图

process_record

2.2 进程与AMS的关联

这里只介绍AMS的进程相关的成员变量:

  1. mProcessNames:数据类型为ProcessMap,以进程名和userId为key来记录ProcessRecord;
    • 添加进程,addProcessNameLocked()
    • 删除进程,removeProcessNameLocked()
  2. mPidsSelfLocked: 数据类型为SparseArray,以进程pid为key来记录ProcessRecord;
    • startProcessLocked(),移除已存在进程,增加新创建进程pid信息;
    • removeProcessLocked,processStartTimedOutLocked,cleanUpApplicationRecordLocked移除进程;
  3. mLruProcesses:数据类型为ArrayList,以进程最近使用情况来排序记录ProcessRecord;
    • 其中第一个元素代表的便是最近最少使用的进程;
    • updateLruProcessLocked()更新进程队列位置;
  4. mRemovedProcesses:数据类型为ArrayList,记录所有需要强制移除的进程;
  5. mProcessesToGc:数据类型为ArrayList,记录系统进入idle状态需执行gc操作的进程;
  6. mPendingPssProcesses:数据类型为ArrayList,记录将要收集内存使用数据PSS的进程;
  7. mProcessesOnHold:数据类型为ArrayList,记录刚开机过程,系统还没与偶准备就绪的情况下, 所有需要启动的进程都放入到该队列;
  8. mPersistentStartingProcesses:数据类型ArrayList,正在启动的persistent进程;
  9. mHomeProcess: 记录包含home Activity所在的进程;
  10. mPreviousProcess:记录用户上一次刚访问的进程;其中mPreviousProcessVisibleTime记录上一个进程的用户访问时间;
  11. mProcessList: 数据类型ProcessList,用于进程管理,Adj常量定义位于该文件;

其中最为常见的是mProcessNames,mPidsSelfLocked,mLruProcesses这3个对象;

2.3 进程与组件的关联

系统AMS这边是由ProcessRecord对象记录进程,进程自身比较重要成员变量如下:

  1. processName:记录进程名,默认情况下进程名和该进程运行的第一个apk的包名是相同的,当然也可以自定义进程名;
  2. pid: 记录进程pid,该值在由进程创建时内核所分配的。
  3. thread:执行完attachApplicationLocked()方法,会把客户端进程ApplicationThread的binder服务的代理端传递到 AMS,并保持到ProcessRecord的成员变量thread;
    • ProcessRecord.makeActive,赋值;
    • ProcessRecord.makeInactive,清空;
  4. info:记录运行在该进程的第一个应用;
  5. pkgList: 记录运行在该进程中所有的包名,比如通过addPackage()添加;
  6. pkgDeps:记录该进程所依赖的包名,比如通过addPackageDependency()添加;
  7. lastActivityTime:每次updateLruProcessLocked()过程会更新该值;
  8. killedByAm:当值为true,意味着该进程是被AMS所杀,而非由于内存低而被LMK所杀;
  9. killed:当值为true,意味着该进程被杀,不论是AMS还是其他方式;
  10. waitingToKill:比如cleanUpRemovedTaskLocked()过程会赋值为”remove task”,当该进程处于后台且

任一组件都运行在某个进程,再来说说ProcessRecord对象中与组件的关联关系:

成员变量说明对应组件
activities记录进程的ActivityRecord列表Activity
services记录进程的ActivityRecord列表Service
executingServices记录进程的正在执行的ActivityRecord列表Service
connections记录该进程bind的ConnectionRecord集合Service
receivers动态注册的广播接收者ReceiverList集合Broadcast
curReceiver当前正在处理的一个广播BroadcastRecordBroadcast
pubProviders该进程发布的ContentProviderRecord的map表ContentProvider
conProviders该进程所请求的ContentProviderConnection列表ContentProvider

说明:

  • connections:举例来说,进程A调用bindService()方法去bind远程进程B的Service。 此时会在进程A的ProcessRecord.connections添加一个ConnectionRecord.
  • pubProviders: 该进程所有对外发布的ContentProvider信息,这是是以ArrayMap形式保存,即 以provider的name为key,以ContentProviderRecord为value的键值对结构体。
  • conProviders: 当进程A调用query()的过程,会执行getContentProvider()方法去向进程B请求 provider的代理。此时会在进程A的ProcessRecord.conProviders添加一个ContentProviderConnection。

三. AMS的组件管理

组件启动,先填充完进程信息,接下来还需要完善组件本身的信息,各个组件在system_server的核心信息记录如下:

  • Service的信息记录在ActiveServices和AMS
  • Broadcast信息记录在BroadcastQueue和AMS
  • Activity信息记录在ActivityStack,ActivityStackSupervisor,以及AMS;
  • Provider信息记录在ProviderMap和AMS;

可见,AMS是整个四大组件最为核心的对象,所有组件都或多或少依赖该对象的数据结构信息。 关系图如下:点击查看大图

four_component

3.1 Activity

AMS对象

public final class ActivityManagerService extends ...{
    //当前聚焦的Activity
    ActivityRecord mFocusedActivity = null;
    //用于管理各个Activity栈
    final ActivityStackSupervisor mStackSupervisor;
}

ASS对象

public final class ActivityStackSupervisor implements DisplayListener {
    //桌面app所在栈
    ActivityStack mHomeStack;

    //当前可以接受Input事件,或许启动下一个Activity的栈
    ActivityStack mFocusedStack;

    //当该值等于mFocusedStack,代表当前栈顶的Activity已进入resumed状态;
    //当该值等于上一个旧栈时,代表正处理activity切换状态;
    private ActivityStack mLastFocusedStack;

    //在完成相应目标前,等待新的Activity成为可见的Activity列表
    final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<>();

    //等待找到下一个可见Activity的等待列表
    final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible = new ArrayList<>();

    //等待找到下一个已启动Activity的等待列表
    final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched = new ArrayList<>();

    //等待上一个activity安置完成,则即将进入被stopped的Activity列表
    final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<>();

    //等待上一个activity安置完成,则即将进入被finished的Activity列表
    final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<>();

    //即将进入sleep状态的进程所对应的Activity列表
    final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>();
}

AS对象

final class ActivityStack{
    //记录该栈中所有的task
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();

    //按LRU方式排序的Activity列表,队尾成员是最新活动的Activity
    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();

    //正在执行pausing过程的Activity
    ActivityRecord mPausingActivity = null;

    //已处于paused状态的Activity
    ActivityRecord mLastPausedActivity = null;

    //已处于Resumed状态的Activity
    ActivityRecord mResumedActivity = null;
}

3.2 Service

[-> ActiveServices.java]

public final class ActiveServices {
    //记录不同User下所有的Service信息
    final SparseArray<ServiceMap> mServiceMap = new SparseArray<>();

    //bind service的连接信息,以IServiceConnection的Bp端作为Keys
    final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections = new ArrayMap<>();

    //已请求启动但尚未启动的Service列表
    final ArrayList<ServiceRecord> mPendingServices = new ArrayList<>();

    //crash后需要计划重启的Service列表
    final ArrayList<ServiceRecord> mRestartingServices = new ArrayList<>();

    //正在执行destroyed的service列表
    final ArrayList<ServiceRecord> mDestroyingServices = new ArrayList<>();
}

3.3 Broadcast

[-> ActivityManagerService.java]

public final class ActivityManagerService extends ...{
    //前台广播队列
    BroadcastQueue mFgBroadcastQueue;
    //后台广播队列
    BroadcastQueue mBgBroadcastQueue;
    //广播队列数组,也就是前台和后台广播队列
    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[2];
    
    //粘性广播,[userId,action,ArrayList<Intent>]
    final SparseArray<ArrayMap<String, ArrayList<Intent>>> mStickyBroadcasts;
    
    //动态注册的广播接收者,其中key为客户端InnerReceiver的Bp端,value为ReceiverList
    final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
    
    //从广播intent到已注册接收者的解析器
    final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver;
}

[-> BroadcastQueue.java]

public final class BroadcastQueue{
    //并行广播列表
    final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
    //串行广播列表
    final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
    
    //即将要处理的串行广播,等待目标进程创建完成。每个广播队列只有一个,其他必须等待该广播完成。
    BroadcastRecord mPendingBroadcast = null;
}

3.4 Provider

[-> ActivityManagerService.java]

public final class ActivityManagerService extends ...{
    //记录系统所有的provider信息
    final ProviderMap mProviderMap;
    
    //记录有client正在等待的provider列表,当provider发布完成则从该队列移除
    final ArrayList<ContentProviderRecord> mLaunchingProviders;
}

[-> ProviderMap.java]

public final class ProviderMap {
    //以provider名字(auth)为key的方式所记录的provider信息
    private final HashMap<String, ContentProviderRecord> mSingletonByName;
    //以provider组件名(ComponentName)为key的方式所记录的provider信息
    private final HashMap<ComponentName, ContentProviderRecord> mSingletonByClass;
    
    //记录不同UserId下的,以auth为key的方式所记录的provider信息
    private final SparseArray<HashMap<String, ContentProviderRecord>> mProvidersByNamePerUser;
    //记录不同UserId下的,以ComponentName为key的方式所记录的provider信息
    private final SparseArray<HashMap<ComponentName, ContentProviderRecord>> mProvidersByClassPerUser;
}

同一个provider组件名,可能对应多个provider名。

四. App端的组件信息

关系图如下:点击查看大图

client_component

App端的组件信息,都保存在ActivityThread和LoadedApk这两个对象,主要保存信息:

  • ActivityThread:记录provider, activity, service在客户端的相关信息;
  • LoadedApk: 记录动态注册的广播接收器,以及bind方式启动service在客户端的相关信息;
Viewing all 119 articles
Browse latest View live