亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Android壁紙服務(wù)的啟動(dòng)過(guò)程

 更新時(shí)間:2021年08月20日 16:51:39   作者:15130140362  
你有設(shè)置過(guò)手機(jī)的壁紙嗎,你知道壁紙是什么樣的程序它是怎么在后臺(tái)運(yùn)行的嗎?這篇文章主要介紹了詳解Android系統(tǒng)壁紙服務(wù)的啟動(dòng)過(guò)程

壁紙基礎(chǔ)

android中的壁紙分為動(dòng)態(tài)壁紙和靜態(tài)壁紙兩種,兩種類(lèi)型的壁紙都以Service的類(lèi)型運(yùn)行在系統(tǒng)后臺(tái)。

  • 靜態(tài)壁紙:僅以圖片的形式進(jìn)行展示對(duì)于靜態(tài)壁紙,可以使用WallpaperManager中的getDrawable()等接口獲取到當(dāng)前的bitmap圖像。
  • 動(dòng)態(tài)壁紙:顯示的內(nèi)容為動(dòng)態(tài)的內(nèi)容,同時(shí)可以對(duì)用戶(hù)的操作做出響應(yīng)對(duì)于動(dòng)態(tài)壁紙的實(shí)時(shí)圖像,是沒(méi)辦法通過(guò)android中原生的接口獲取到,需要獲取到動(dòng)態(tài)壁紙的圖像得自己修改源碼。

壁紙實(shí)現(xiàn)時(shí)涉及的幾個(gè)主要的類(lèi):

  • WallpaperService及其內(nèi)部類(lèi)Engine:壁紙?jiān)赪allpaperService這個(gè)服務(wù)中運(yùn)行,當(dāng)需要實(shí)現(xiàn)自己的壁紙時(shí),繼承和實(shí)現(xiàn)這個(gè)類(lèi),是首先需要做的。Engine是WallpaperService中的一個(gè)內(nèi)部類(lèi),實(shí)現(xiàn)了壁紙服務(wù)窗口的創(chuàng)建以及Surface的維護(hù),同時(shí)Engine內(nèi)部類(lèi)還提供了onVisibilityChanged(),onCommand()等回調(diào)方法,用于可見(jiàn)狀態(tài)變化和用戶(hù)觸摸事件等。Engine類(lèi)因此也是壁紙實(shí)現(xiàn)的核心類(lèi),實(shí)現(xiàn)和重寫(xiě)其接口在開(kāi)發(fā)中也相當(dāng)重要。
  • WallpaperManagerService和WallpaperManager:WallpaperManagerService用于管理壁紙的運(yùn)行與切換,并通過(guò)WallpaperManager對(duì)外界提供操作壁紙的接口。
  • WindowMangerService:該類(lèi)用于計(jì)算壁紙窗口的Z序,可見(jiàn)性以及為壁紙窗口應(yīng)用動(dòng)畫(huà)。

壁紙服務(wù)的兩種啟動(dòng)場(chǎng)景

非首次重啟壁紙服務(wù)啟動(dòng)流程

SystemService進(jìn)程啟動(dòng)時(shí),會(huì)啟動(dòng)各種系統(tǒng)服務(wù)。在該類(lèi)的startOtherServices()方法中會(huì)首先拉起
WallpaperManagerService,通過(guò)該類(lèi),WallpaperService后面才得以啟動(dòng)。

            if (context.getResources().getBoolean(R.bool.config_enableWallpaperService)) {
                t.traceBegin("StartWallpaperManagerService");
                mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS);
                t.traceEnd();
            } else {
                Slog.i(TAG, "Wallpaper service disabled by config");
            }

WallpaperManagerService啟動(dòng)之后systemReady()方法中會(huì)通過(guò)loadSettingsLocked()方法加載用戶(hù)設(shè)置過(guò)的壁紙信息,然后監(jiān)聽(tīng)用戶(hù)切換用戶(hù)switchUser(),切換用戶(hù)時(shí),switchWallpaper()會(huì)調(diào)用bindWallpaperComponentLocked()方法拉起對(duì)應(yīng)的壁紙服務(wù)。

手動(dòng)切換時(shí)壁紙服務(wù)的啟動(dòng)流程

手動(dòng)切換壁紙服務(wù)時(shí)需要通過(guò)WallpaperManager.getIWallpaperManager().setWallpaperComponent()方法完成,我們?cè)谶@個(gè)接口中傳入壁紙服務(wù)對(duì)應(yīng)的ComponentName,getIWallpaperManager返回的是WallpaperManagerService的Bp(binder proxy binder代理)端,在WallpaperManagerService端,我們可以查看到setWallpaperComponent的具體實(shí)現(xiàn),

private void setWallpaperComponent(ComponentName name, int userId) {
        ...
        /* 首先調(diào)用該方法的時(shí)候回去校驗(yàn)權(quán)限,該權(quán)限定義在frameworks/base/core/res/AndroidManifest.xml,
            <permission android:name="android.permission.SET_WALLPAPER_COMPONENT"
        android:protectionLevel="signature|privileged" />
        查看protectionLevel,只有是特權(quán)應(yīng)用或者系統(tǒng)簽名的應(yīng)用才能獲取到這個(gè)系統(tǒng)權(quán)限,所以普通的應(yīng)用是沒(méi)有辦法進(jìn)行壁紙?jiān)O(shè)置的
        */
        checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);

        int which = FLAG_SYSTEM;
        boolean shouldNotifyColors = false;
        WallpaperData wallpaper;

        synchronized (mLock) {
            Slog.v(TAG, "setWallpaperComponent name=" + name);
            /*
              此處會(huì)先通過(guò)當(dāng)前的用戶(hù)ID獲取到與該用戶(hù)相關(guān)的壁紙信息,WallpaperManagerService支持多用戶(hù)機(jī)制,用戶(hù)的信息在mWallpaperMap中存儲(chǔ),每一個(gè)用戶(hù)對(duì)應(yīng)一個(gè)WallpaperData,WallpaperData存儲(chǔ)壁紙相關(guān)信息
			*/
            wallpaper = mWallpaperMap.get(userId);
            if (wallpaper == null) {
                throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
            }
      		 ...
      		    // 在這里真正會(huì)去拉起對(duì)應(yīng)的WallPaperService
                if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
              ...
    }

setWallpaperComponent最終也是通過(guò)bindWallpaperComponentLocked拉起壁紙服務(wù)

壁紙服務(wù)啟動(dòng)過(guò)程

1.校驗(yàn)是否是壁紙服務(wù)

bindWallpaperComponentLocked()方法將會(huì)啟動(dòng)該ComponentName所指定的WallpaperService,在啟動(dòng)的時(shí)候首先會(huì)進(jìn)行校驗(yàn),以確定待拉起的服務(wù)是一個(gè)壁紙服務(wù),

    private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
            boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
      	...
            int serviceUserId = wallpaper.userId;
            ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
                    PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
            if (si == null) {
                // The wallpaper component we're trying to use doesn't exist
                Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
                return false;
            }
            /*
            第一個(gè)校驗(yàn):  
			啟動(dòng)的時(shí)候首先會(huì)校驗(yàn)這個(gè)壁紙服務(wù)是否聲明權(quán)限為BIND_WALLPAPER權(quán)限,
              該權(quán)限的定義同樣也在fwk/base/core/res/manifest.xml
                  <permission android:name="android.permission.BIND_WALLPAPER"
        android:protectionLevel="signature|privileged" />
			  該權(quán)限也是系統(tǒng)級(jí)別的,防止三方應(yīng)用切換壁紙,
			*/
            if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
                String msg = "Selected service does not have "
                        + android.Manifest.permission.BIND_WALLPAPER
                        + ": " + componentName;
                if (fromUser) {
                    throw new SecurityException(msg);
                }
                Slog.w(TAG, msg);
                return false;
            }

            WallpaperInfo wi = null;

            Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
            if (componentName != null && !componentName.equals(mImageWallpaper)) {
                // Make sure the selected service is actually a wallpaper service.
                			/*
			   第二個(gè)校驗(yàn):
			   這個(gè)檢查來(lái)校驗(yàn)服務(wù)是否聲明了android.service.wallpaper.WallpaperService這個(gè)action。如果這個(gè)服務(wù)沒(méi)有聲明這個(gè)action的話那么,ris中就不會(huì)含有這個(gè)component信息,
			*/
                List<ResolveInfo> ris =
                        mIPackageManager.queryIntentServices(intent,
                                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                                PackageManager.GET_META_DATA, serviceUserId).getList();
                for (int i=0; i<ris.size(); i++) {
                    ServiceInfo rsi = ris.get(i).serviceInfo;
                    if (rsi.name.equals(si.name) &&
                            rsi.packageName.equals(si.packageName)) {
                        try {
                        /*
                          第三個(gè)檢查:
                          獲取名為android.service.wallpaper中的meta-data信息,該meta-data信息中提供了縮略圖,開(kāi)發(fā)者,簡(jiǎn)單的描述等。會(huì)將這些信息轉(zhuǎn)換成WallpaperInfo
                        */
                            wi = new WallpaperInfo(mContext, ris.get(i));
                        } catch (XmlPullParserException e) {
                            if (fromUser) {
                                throw new IllegalArgumentException(e);
                            }
                            Slog.w(TAG, e);
                            return false;
                        } catch (IOException e) {
                            if (fromUser) {
                                throw new IllegalArgumentException(e);
                            }
                            Slog.w(TAG, e);
                            return false;
                        }
                        break;
                    }
                }
                if (wi == null) {
                    String msg = "Selected service is not a wallpaper: "
                            + componentName;
                    if (fromUser) {
                        throw new SecurityException(msg);
                    }
                    Slog.w(TAG, msg);
                    return false;
                }
            }

			// 當(dāng)壁紙服務(wù)支持在ambient模式下進(jìn)行繪制的時(shí)候,需要檢查是否有AMBIENT_WALLPAPER權(quán)限,
            if (wi != null && wi.supportsAmbientMode()) {
                final int hasPrivilege = mIPackageManager.checkPermission(
                        android.Manifest.permission.AMBIENT_WALLPAPER, wi.getPackageName(),
                        serviceUserId);
                if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
                    String msg = "Selected service does not have "
                            + android.Manifest.permission.AMBIENT_WALLPAPER
                            + ": " + componentName;
                    if (fromUser) {
                        throw new SecurityException(msg);
                    }
                    Slog.w(TAG, msg);
                    return false;
                }
            }
            // 檢驗(yàn)完畢,這里才會(huì)開(kāi)始bind 壁紙服務(wù),如果校驗(yàn)失敗的話,會(huì)返回false
			...
    }

上面的校驗(yàn)可以看出一共校驗(yàn)了三個(gè)條件:

  1. 啟動(dòng)的時(shí)候首先會(huì)校驗(yàn)這個(gè)壁紙服務(wù)是否聲明權(quán)限為BIND_WALLPAPER權(quán)限, 該權(quán)限的定義在fwk/base/core/res/manifest.xml中,< permission android:name=“android.permission.BIND_WALLPAPER”
    android:protectionLevel=“signature|privileged” />
    該權(quán)限也是系統(tǒng)級(jí)別的,防止三方應(yīng)用切換壁紙。
  2. 這個(gè)檢查來(lái)校驗(yàn)服務(wù)是否聲明了android.service.wallpaper.WallpaperService這個(gè)action。如果這個(gè)服務(wù)沒(méi)有聲明這個(gè)action的話那么,ris中就不會(huì)含有這個(gè)component信息。
  3. 獲取名為android.service.wallpaper中的meta-data信息,該meta-data信息中提供了縮略圖,開(kāi)發(fā)者,簡(jiǎn)單的描述等。會(huì)將這些信息轉(zhuǎn)換成WallpaperInfo。

2.綁定壁紙服務(wù)

壁紙服務(wù)的校驗(yàn)滿(mǎn)足后,開(kāi)始啟動(dòng)和綁定目標(biāo)服務(wù):

    private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
            boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
	// 校驗(yàn)服務(wù)是否符合要求結(jié)束后,開(kāi)始著手啟動(dòng)服務(wù)
	...
	//1. 創(chuàng)建一個(gè)WallpaperConnection,該對(duì)象可以監(jiān)聽(tīng)和WallpaperService之間的連接狀態(tài),同時(shí)歸對(duì)象繼承了IWallpaperConnection.Stub,這樣該對(duì)象有擁有了跨進(jìn)程通信的能力,當(dāng)服務(wù)綁定成功后,onServiceConnected()方法調(diào)用中,WallpaperConnection實(shí)力會(huì)被發(fā)送到WallpaperService,該實(shí)例可以用于WallpaperService想WallpaperManagerService進(jìn)行通信的橋梁。
	intent.setComponent(componentName);
    intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                    com.android.internal.R.string.wallpaper_binding_label);
    ...
    /* 2. 這里啟動(dòng)指定的壁紙服務(wù),服務(wù)啟動(dòng)后,壁紙還沒(méi)有辦法進(jìn)行顯示,還需要WallpaperConnection.onServiceConnected中進(jìn)行相應(yīng)的處理*/
    if (!mContext.bindServiceAsUser(intent, newConn,Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI| Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE | 
    Context.BIND_INCLUDE_CAPABILITIES,new UserHandle(serviceUserId))) {
}

	/*3. 新的壁紙服務(wù)啟動(dòng)之后,就開(kāi)始銷(xiāo)毀舊服務(wù)*/
	if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null && !wallpaper.equals(mFallbackWallpaper)) {
         detachWallpaperLocked(mLastWallpaper);
    }
    
    /* 4.將新的壁紙服務(wù)信息進(jìn)行保存*/
	wallpaper.wallpaperComponent = componentName;
    wallpaper.connection = newConn;
    ...

bindWallpaperComponentLocked函數(shù)在拉起壁紙服務(wù)的時(shí)候主要做了下面幾件事情:

  • 創(chuàng)建了WallpaperConnection對(duì)象,由于實(shí)現(xiàn)了ServiceConnection接口,所以WallpaperConnection可以用來(lái)監(jiān)聽(tīng)和壁紙服務(wù)的連接狀態(tài),另外由于繼承了IWallpoaperConnection.Stub接口,所以WallpaperConnection具有了跨進(jìn)程通信的能力。
  • 啟動(dòng)壁紙服務(wù):這里僅僅是拉起服務(wù),和拉起普通服務(wù)的方式基本一致,拉起方式上則使用了bindServiceAsUser,查看官方注解,該接口增加了校驗(yàn)該用戶(hù)是否能拉起該服務(wù),其余的行為和bindService相同。
  • 保存當(dāng)前WallpaperConnection實(shí)例,ConponentName,到WallpaperData中

bindWallpaperComponentLocked()函數(shù)將壁紙服務(wù)拉了起來(lái),但是僅僅將壁紙服務(wù)拉起來(lái)是沒(méi)有辦法顯示圖像的,因?yàn)閱?dòng)的服務(wù)并沒(méi)有窗口令牌,這樣就沒(méi)辦法添加窗口。剩下的這部分顯示的工作在WallpaperConnection的onServiceConnected()方法中進(jìn)行,在該回調(diào)中同樣也能拿到壁紙服務(wù)端服務(wù)端提供的Binder對(duì)象。
WallpaperService在被bind的時(shí)候返回了一個(gè)IWallpaperServiceWrapper對(duì)象,從代碼中可以看到,該對(duì)象中保存了WallpaperService實(shí)例,看了代碼后再去理解這個(gè)對(duì)象的命名(包裝WallpaperService),果然名副其實(shí)。

  class IWallpaperServiceWrapper extends IWallpaperService.Stub {
        private final WallpaperService mTarget;
        private IWallpaperEngineWrapper mEngineWrapper;

        public IWallpaperServiceWrapper(WallpaperService context) {
            mTarget = context;
        }
        
        @Override
        public void attach(IWallpaperConnection conn, IBinder windowToken,
        int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,int displayId) {
		...
		}

        @Override
        public void detach() {
        ...
        }
    }

該接口中一共有兩個(gè)接口,attach和detach,attach接口在創(chuàng)建的時(shí)候可以將相關(guān)信息傳遞到壁紙服務(wù)中,對(duì)應(yīng)的,detach接口在服務(wù)銷(xiāo)毀的時(shí)候調(diào)用。

3.引擎的創(chuàng)建和初始化

引擎的創(chuàng)建準(zhǔn)備工作開(kāi)始于onServiceConnected()回調(diào)處,該回調(diào)會(huì)傳遞壁紙服務(wù)需要的窗口令牌和ServiceConnection對(duì)象等。
WallpaperManagerService.java

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            synchronized (mLock) {
                if (mWallpaper.connection == this) {
                    mService = IWallpaperService.Stub.asInterface(service);
                    attachServiceLocked(this, mWallpaper);
                    // XXX should probably do saveSettingsLocked() later
                    // when we have an engine, but I'm not sure about
                    // locking there and anyway we always need to be able to
                    // recover if there is something wrong.
                    if (!mWallpaper.equals(mFallbackWallpaper)) {
                    	// 保存當(dāng)前的壁紙信息到文件系統(tǒng)中,這樣重啟的時(shí)候就可以加載之前用戶(hù)設(shè)置過(guò)的壁紙
                        saveSettingsLocked(mWallpaper.userId);
                    }
                    FgThread.getHandler().removeCallbacks(mResetRunnable);
                    mContext.getMainThreadHandler().removeCallbacks(mTryToRebindRunnable);
                }
            }
        }

onServiceConnected()函數(shù)中,首先將返回的binder對(duì)象進(jìn)行了保存,然后在attachServiceLocked()方法中會(huì)調(diào)用connectLocked()方法,connectLocked()接口中調(diào)用了attach方法傳遞了壁紙服務(wù)所需要的信息。

            void connectLocked(WallpaperConnection connection, WallpaperData wallpaper) {
                ...
                mWindowManagerInternal.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);
                final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
                try {
                    connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
                            wpdData.mWidth, wpdData.mHeight,
                            wpdData.mPadding, mDisplayId);
                }
                ...
            }

attach接口回傳了許多信息,其中

  • connection為WallpaperConnection的實(shí)例。WallpaperConnection之所以具有跨進(jìn)程通信的能力是因?yàn)槔^承了IWallpaperConnection.Stub類(lèi),該Stub對(duì)象中比較重要的一個(gè)接口就是attachEngine(),因?yàn)镋ngine實(shí)現(xiàn)才是動(dòng)態(tài)壁紙的核心,WallpaperService會(huì)將創(chuàng)建好的Engine引用通過(guò)attachEngine()回傳給WallpaperManagerService進(jìn)行管理。
  • mToken是向WMS注冊(cè)過(guò)的窗口令牌,只有擁有了這個(gè)令牌,WallpaperService才有權(quán)添加壁紙窗口。

傳遞了WallpaperService需要的信息之后,WallPaperService開(kāi)始進(jìn)行引擎的創(chuàng)建。查看WallpaperService中attach()方法的實(shí)現(xiàn),

    class IWallpaperServiceWrapper extends IWallpaperService.Stub {
        ...
        @Override
        public void attach(IWallpaperConnection conn, IBinder windowToken,
                int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
                int displayId) {
            mEngineWrapper = new IWallpaperEngineWrapper(mTarget, conn, windowToken,
                    windowType, isPreview, reqWidth, reqHeight, padding, displayId);
        }
        ...
     }

attach方法創(chuàng)建了一個(gè)IWallpaperEngineWrapper,顧名思義,該對(duì)象有壁紙服務(wù)創(chuàng)建的引擎的引用,在創(chuàng)建IWallpaperEngineWrapper對(duì)象的時(shí)候,會(huì)發(fā)送DO_ATTACH消息,該消息用于壁紙服務(wù)引擎的創(chuàng)建,

IWallpaperEngineWrapper.java
        IWallpaperEngineWrapper(WallpaperService context,
                IWallpaperConnection conn, IBinder windowToken,
                int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
                int displayId) {
            mCaller = new HandlerCaller(context, context.getMainLooper(), this, true);
        	...
            Message msg = mCaller.obtainMessage(DO_ATTACH);
            mCaller.sendMessage(msg);
        }
...
		@Override
        public void executeMessage(Message message) {
            switch (message.what) {
                case DO_ATTACH: {
                    try {
                    // 將IWallpaperEngineWapper對(duì)象傳遞給WallpaperConnection進(jìn)行保存,通過(guò)這個(gè)引用,WallpaperManagerService也可以通過(guò)它與engine進(jìn)行通信
                        mConnection.attachEngine(this, mDisplayId);
                    } catch (RemoteException e) {
                        Log.w(TAG, "Wallpaper host disappeared", e);
                        return;
                    }
                    // 創(chuàng)建一個(gè)引擎,該方法為抽象方法,需要子類(lèi)根據(jù)自身實(shí)現(xiàn)具體的引擎
                    Engine engine = onCreateEngine();
                    mEngine = engine;
                    mActiveEngines.add(engine);
					// 該方法中會(huì)完成窗口的創(chuàng)建,surface創(chuàng)建等工作。
                    engine.attach(this);
                    return;
                }

由于mConnection.attachEngine()方法將IWallpaperEngineWrapper傳遞給了WallpaperManagerService,因此WallpaperManagerService可以轉(zhuǎn)發(fā)相關(guān)的請(qǐng)求和設(shè)置到Engine對(duì)象中,實(shí)現(xiàn)WallpaperManagerService到壁紙的通信。
onCreateEngine方法執(zhí)行后,引擎創(chuàng)建完成,之后通過(guò)engine.attach()方法進(jìn)行引擎相關(guān)的初始化:

        void attach(IWallpaperEngineWrapper wrapper) {
            ...
            mIWallpaperEngine = wrapper;
            mCaller = wrapper.mCaller;
            mConnection = wrapper.mConnection;
            mWindowToken = wrapper.mWindowToken;
            mSurfaceHolder.setSizeFromLayout();
            mInitializing = true;

			// 這個(gè)session用于和WMS進(jìn)行通信
            mSession = WindowManagerGlobal.getWindowSession();

			// mWindow是一個(gè)IWindow對(duì)象,用于接收從WMS發(fā)送過(guò)來(lái)的消息
            mWindow.setSession(mSession);

            mLayout.packageName = getPackageName();
            mIWallpaperEngine.mDisplayManager.registerDisplayListener(mDisplayListener,
                    mCaller.getHandler());
            mDisplay = mIWallpaperEngine.mDisplay;
            mDisplayContext = createDisplayContext(mDisplay);
            mDisplayState = mDisplay.getState();

            if (DEBUG) Log.v(TAG, "onCreate(): " + this);
            // 子類(lèi)可以重寫(xiě)該接口,在該接口中可以修改mSurfaceHolder相關(guān)的屬性,這個(gè)時(shí)候
            // 窗口尚未創(chuàng)建。設(shè)置的相關(guān)屬性將在updateSurface中創(chuàng)建窗口時(shí)使用
            onCreate(mSurfaceHolder);

            mInitializing = false;

            mReportedVisible = false;
			
			// updateSurface會(huì)進(jìn)行窗口以及Surface的創(chuàng)建。
            updateSurface(false, false, false);
        }

attach方法執(zhí)行的完成,標(biāo)志著壁紙啟動(dòng)的完成,之后可以調(diào)用壁紙的surface顯示圖像。

壁紙服務(wù)的啟動(dòng)流程總結(jié)

壁紙服務(wù)的啟動(dòng)相比于普通服務(wù)的啟動(dòng)較為復(fù)雜,接下來(lái)用下面的示意圖對(duì)整體的流程進(jìn)行梳理:

在這里插入圖片描述

壁紙服務(wù)在啟動(dòng)的時(shí)候,大體可以分為兩個(gè)階段,首先就要是拉起對(duì)應(yīng)的服務(wù),拉起服務(wù)后然后將WindowToken等參數(shù)傳遞給引擎進(jìn)行窗口的創(chuàng)建,surface的創(chuàng)建。在WallpaperManagerService和WallpaperService交互的過(guò)程中,主要有下面三個(gè)跨進(jìn)程通信的Binder對(duì)象:

  • WallpaperConnection:實(shí)現(xiàn)在WallpaperManagerService中,并通過(guò)IWallpaperService.attach回調(diào)傳遞給了IWallpaperEngineWrapper,通過(guò)WallpaperConnection.attachEngine()方法,WallpaperService將IWallpaperEngineWrapper回傳給了WallpaperManagerService,實(shí)現(xiàn)了雙向的通信。
  • IWallpaperService:實(shí)現(xiàn)在WallpaperService中,該對(duì)象提供了attach方法,用于從WallpaperManagerService獲取引擎創(chuàng)建時(shí)需要的WindowToken等信息。
  • IWallpaperEngineWrapper:實(shí)現(xiàn)在壁紙服務(wù)進(jìn)程中,同時(shí)引用交給了WallpaperManagerService,該對(duì)象封裝了Engine類(lèi),WallpaperManagerService對(duì)引擎相關(guān)的控制需要通過(guò)該對(duì)象提供的接口實(shí)現(xiàn)。

自己最近因?yàn)樾枰ㄎ灰粋€(gè)開(kāi)機(jī)壁紙服務(wù)啟動(dòng)慢的問(wèn)題,所以熟悉了下壁紙服務(wù)的啟動(dòng)過(guò)程,在此記錄啟動(dòng)流程。定位該問(wèn)題梳理從bind到onServiceConnected和引擎相關(guān)初始化,對(duì)比每一個(gè)階段的時(shí)間,最終確定問(wèn)題的原因。
參考:

  • 《深入理解Android卷3》第八章:深入理解android壁紙服務(wù)
  • framework-base源碼

到此這篇關(guān)于詳解Android壁紙服務(wù)的啟動(dòng)過(guò)程的文章就介紹到這了,更多相關(guān)Android壁紙內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論