0%

Print框架整理

1. 开篇

涉及的主要文件:

com.android.server.print

系统打印服务, 打印服务是一种插件( plug-in components),它能够通过一些标准协议和打印机通讯。这些服务像一座桥,处于系统和打印机之间。因此,打印机和打印协议的具体实现从系统中分离的,能够独立开发和更新。该处讲解的是和打印插件关联的系统服务.

/frameworks/base/services/print/java/com/android/server/print/

1
2
3
4
5
6
7
8
9
10
11
12
13
/home/newdisk/local/SPREADTRUM/liguang.zhang/remote_disk/sp8.1_trunk/frameworks/base/services/print/java/com/android/server/print$ lltotal 220
drwxr-xr-x 1 2516 2000 4096 Jun 25 14:20 ./
drwxr-xr-x 1 2516 2000 4096 Nov 8 2017 ../
# PrintService插件管理类.
-rw-r--r-- 1 2516 2000 41807 Jun 25 16:21 PrintManagerService.java
# 负责和PrintService插件进行bind, 以及插件的状态进行关联
-rw-r--r-- 1 2516 2000 34039 Jun 25 14:20 RemotePrintService.java
# 推荐选择默认的打印插件
-rw-r--r-- 1 2516 2000 8869 Jun 25 14:20 RemotePrintServiceRecommendationService.java
# 打印机后台处理程序,打印任务工作状态相关.
-rw-r--r-- 1 2516 2000 34260 Nov 8 2017 RemotePrintSpooler.java
# 和用户安装的打印服务相关的管理,通过userState中转转发和PrintManagerService进行交互
-rw-r--r-- 1 2516 2000 85628 Jun 25 15:47 UserState.java

2. PrintManagerService初始化

PrintManagerService(简写PMS) 初始化

SystemServer中启动PMS

1
2
3
4
5
6
7
8
9
10
11
12
13
            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
traceBeginAndSlog("StartPrintManager");
mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
traceEnd();
}
// onStart注册'print'的服务
public void onStart() {
publishBinderService(Context.PRINT_SERVICE, mPrintManagerImpl);
}
// 监听DISABLED_PRINT_SERVICES 字段, 表示禁用的打印服务插件, 如果该字段变化,则需要重新更新UserState的关联的打印插件.
registerContentObservers();
// 监听PACKAGE ADD/REMOVE/MODIFY等的广播, 用来更新打印插件服务的状态
registerBroadcastReceivers();

跟User关联的userState实例通过getOrCreateUserStateLocked方法创建并保存到
PMS的mUserStates中(userid–UserState map)

3. UserState 初始化

  1. 关联 RemotePrintSpooler类. 该类主要是讲远程打印机的状态本地化, 实现监控remote print的状态. (后台作业)

  2. UserStateHandler, 用于处理

    PRINT_JOB_STATE_CHANGED/

    PRINT_SERVICES_CHANGED/

    PRINT_SERVICES_RECOMMENDATIONS_UPDATED

    CHECK_CONFIG_CHANGED事件. 主要为前三类.

  3. 读取已经为该用户安装的printService插件. 满足几个条件:

    manifest定义举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
            <service
    android:name="android.print.cts.services.FirstPrintService"
    1. android:permission="android.permission.BIND_PRINT_SERVICE">
    <intent-filter>
    2. <action android:name="android.printservice.PrintService" />
    </intent-filter>
    <meta-data
    3. android:name="android.printservice"
    android:resource="@xml/printservice">
    </meta-data>
    </service>
    // printservice.xml 配置打印机的相关页面.
    <print-service xmlns:android="http://schemas.android.com/apk/res/android"
    // settingsActivity在打印插件开启界面右上角的菜单里,用于配置插件
    android:settingsActivity="android.print.cts.services.SettingsActivity"
    // 在自定义的 addPrintersActivity 中,系统不会自动触发打印机寻找过程,需要自行处理
    android:addPrintersActivity="android.print.cts.services.AddPrintersActivity"
    //advancedPrintOptionsActivity则是在打印文件的界面上点击更多箭头里出现的MORE OPTIONS选项触发,这个activity用配置打印机的跟多信息。
    android:advancedPrintOptionsActivity="android.print.cts.services.CustomPrintOptionsActivity"/>
  4. store the disabled services, 保存到表中 Settings.Secure.ENABLED_PRINT_SERVICES, 处理mDisabledServices

  5. onConfigurationChangedLocked根据mDisabledServices和mActiveServices添加或删除打印插件托管,并通过MSG_DISPATCH_PRINT_SERVICES_CHANGED回调IPrintServicesChangeListener的onPrintServicesChanged, 该listener通过*addPrintServicesChangeListener*进行注册的.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public UserState(Context context, int userId, Object lock, boolean lowPriority) {
    // 初始化RemotePrintSpooler,
    mSpooler = new RemotePrintSpooler(context, userId, lowPriority, this);
    mHandler = new UserStateHandler(context.getMainLooper());

    synchronized (mLock) {
    readInstalledPrintServicesLocked();
    upgradePersistentStateIfNeeded();
    readDisabledPrintServicesLocked();
    }

    // Some print services might have gotten installed before the User State came up
    prunePrintServices();

    synchronized (mLock) {
    onConfigurationChangedLocked();
    }
    }

需要重点看下onConfigurationChangedLocked函数的处理.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
private void onConfigurationChangedLocked() {
ArrayList<ComponentName> installedComponents = getInstalledComponents();

final int installedCount = installedComponents.size();
for (int i = 0; i < installedCount; i++) {
ComponentName serviceName = installedComponents.get(i);
// 1. 既没在mDisabledServices也没在mActiveServices中, 初始化RemotePrintService,并调用addServiceLocked函数
if (!mDisabledServices.contains(serviceName)) {
if (!mActiveServices.containsKey(serviceName)) {
RemotePrintService service = new RemotePrintService(
mContext, serviceName, mUserId, mSpooler, this);
addServiceLocked(service);
}
} else {
// 2. 在mDisabledServices中,调用removeServiceLocked
RemotePrintService service = mActiveServices.remove(serviceName);
if (service != null) {
removeServiceLocked(service);
}
}
}

Iterator<Map.Entry<ComponentName, RemotePrintService>> iterator =
mActiveServices.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<ComponentName, RemotePrintService> entry = iterator.next();
ComponentName serviceName = entry.getKey();
RemotePrintService service = entry.getValue();
//3. 删除没有安装的过期的RemotePrintService实例
if (!installedComponents.contains(serviceName)) {
removeServiceLocked(service);
iterator.remove();
}
}
//4. 回调 IPrintServicesChangeListener的 onPrintServicesChanged
// listener是通过addPrintServicesChangeListener添加的.
onPrintServicesChanged();
}

1.0 RemotePrintService的初始化
+ mCallbacks = callbacks; // RemotePrintService的callback成员为UserState
+ serviceName
+ userid
+ spooler // 关联UserState的spooler.
+ mPrintService// 关联到打印插件
1.1. 将该printService插件加到mActiveServices中
1.2. 回调mPrinterDiscoverySession onServiceAddedLocked(RemotePrintService)方法
// PrinterDiscoverySessionMediator为UserState的内部类, 主要作用是跟RemotePrintService以及Session状态关联,通过SessionHandler控制RemotePrintService. SessionHandler-->RemotePrintService.Handler-->bind printService-->PrintService插件todo task.
private PrinterDiscoverySessionMediator mPrinterDiscoverySession;

public void onServiceAddedLocked(RemotePrintService service) {
if (mIsDestroyed) {
Log.w(LOG_TAG, "Not updating added service - session destroyed");
return;
}
// Tell the service to create a session.
1.2.1 MSG_CREATE_PRINTER_DISCOVERY_SESSION 建立一个session
mSessionHandler.obtainMessage(
SessionHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
service).sendToTarget();
1.2.2 通过session查找打印机
// Start printer discovery if necessary.
if (!mStartedPrinterDiscoveryTokens.isEmpty()) {
mSessionHandler.obtainMessage(
SessionHandler.MSG_START_PRINTER_DISCOVERY,
service).sendToTarget();
}
// Start tracking printers if necessary
1.2.3 根据RemotePrintService 绑定的打印插件, 与搜索到的打印机, 打印机属于该打印插件时,启动tracking.
final int trackedPrinterCount = mStateTrackedPrinters.size();
for (int i = 0; i < trackedPrinterCount; i++) {
PrinterId printerId = mStateTrackedPrinters.get(i);
if (printerId.getServiceName().equals(service.getComponentName())) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = service;
args.arg2 = printerId;
mSessionHandler.obtainMessage(SessionHandler
.MSG_START_PRINTER_STATE_TRACKING, args)
.sendToTarget();
}
}
}
2. removeServiceLocked
private void removeServiceLocked(RemotePrintService service) {
// Fail all print jobs.
2.1 failActivePrintJobsForService(service.getComponentName());
// If discovery is in progress, tear down the service.
if (mPrinterDiscoverySession != null) {
2.2 mPrinterDiscoverySession.onServiceRemovedLocked(service);
} else {
// Otherwise, just destroy it.
service.destroy();
}
}
2.1 // Fail all print jobs.
private void failScheduledPrintJobsForServiceInternal(ComponentName serviceName) {
// 根据打印插件名查找所有进行着的后台作业
List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(serviceName,
PrintJobInfo.STATE_ANY_SCHEDULED, PrintManager.APP_ID_ANY);
if (printJobs == null) {
return;
}
try {
final int printJobCount = printJobs.size();
for (int i = 0; i < printJobCount; i++) {
PrintJobInfo printJob = printJobs.get(i);
// 全部设为FAILED state.
mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
mContext.getString(R.string.reason_service_unavailable));
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
2.2. // If discovery is in progress, tear down the service.
public void onServiceRemovedLocked(RemotePrintService service) {
if (mIsDestroyed) {
Log.w(LOG_TAG, "Not updating removed service - session destroyed");
return;
}
// Remove the reported and tracked printers for that service.
// 删除为该打印插件服务搜索到的打印机或正在跟踪的打印机
ComponentName serviceName = service.getComponentName();
// mPrinters.remove(removedPrinterIds.get(i));
// 从mPrinter中删除. 并通知给通过addObserverLocked添加的observer删除了这些打印机.
// handlePrintersRemoved(observer, removedPrinterIds); 回调 observer.onPrintersRemoved(new ParceledListSlice<PrinterId>(printerIds))方法
removePrintersForServiceLocked(serviceName);
2.2.1 // 最后进到RemotePrintService的destroy流程
service.destroy();
}
2.2.1 //service.destroy(); --> RMS.handleDestroy
private void handleDestroy() {
// Stop tracking printers.
// 回调打印插件的stopPrinterStateTracking方法.
// tracking 是持续跟踪打印机最新状态的机制.
stopTrackingAllPrinters();
// Stop printer discovery.
if (mDiscoveryPriorityList != null) {
handleStopPrinterDiscovery();
}
// Destroy the discovery session.
if (mHasPrinterDiscoverySession) {
// 回调 mPrintService.stopPrinterDiscovery();方法. 停止该打印插件搜索打印机的过程.
handleDestroyPrinterDiscoverySession();
}

// Unbind. RMS unbind 该打印插件.
ensureUnbound();

// Done
mDestroyed = true;
}

3.1. 小节

该处主要涉及UserState的初始化. UserState是一个很重要的桥梁,关联到

  • RemotePrintService

    每个RMS实例绑定到一个打印插件. UserState通过mActiveServices保存了激活状态的RMS.通过mDisabledServices保存了弃用的RMS. RMS是以其绑定的打印插件compnent名为标志的. 当打印插件卸载时, 对应的RMS也要销毁. 当打印插件处于关闭状态时, RMS为Disable状态. 通过UserState的SessionHandler嫁接到RMS的handler中,并通过RMS的mPrintService控制打印插件进行真正的任务处理.

  • IPrinterDiscoveryObserver (通过addObserverLocked添加)

    该observer监听打印机的搜索过程, 这个地方主要关联到

    frameworks/base/core/java/android/print/PrinterDiscoverySession.java

    该类作为客户端,提供了setOnPrintersChangeListener方法, 通过observer的中转, 将打印机的状态变化可以通知到外部的app.

    ex: Settings app

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    if (mDiscoverySession == null) {
    PrintManager printManager = (PrintManager) getContext()
    .getSystemService(Context.PRINT_SERVICE);
    //SPRD 742355 main thread block by binder caused anr
    new AsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackground(Void... params) {
    mDiscoverySession = printManager.createPrinterDiscoverySession();
    return null;
    }
    @Override
    protected void onPostExecute(Void result) {
    if (mDiscoverySession == null) {
    return;
    }
    mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener() {
    @Override
    public void onPrintersChanged() {
    deliverResult(new ArrayList<PrinterInfo>(
    mDiscoverySession.getPrinters()));
    }
    });
    mDiscoverySession.startPrinterDiscovery(null);
    }
    }.execute();
    }
  • IPrintServicesChangeListener(通过addPrintServicesChangeListener添加)通过PrintManager中转,提供给外部app使用. 通知RMS状态的变更. 外部可以通过mPrintManager.getPrintServices拿到打印插件.

    1
    2
    3
    4
    5
    // ENABLED_SERVICES | DISABLED_SERVICES | ALL_SERVICES
    List<PrintServiceInfo> infos = mPrintManager.getPrintServices(
    PrintManager.ENABLED_SERVICES);
    addPrintServicesChangeListener
    mPrintManager.addPrintServicesChangeListener(this, null);
  • RemotePrintSpooler

    bind到后台作业服务, “com.android.printspooler”

    源码中默认为PrintSpooler frameworks/base/packages/PrintSpooler/

    通过setClientLocked设置PrintSpoolerClient为PrintSpooler的client.

    PrintSpoolerClient 类通过callbacks 实际传导到userState类中, userState再根据消息类别转发到不同的地方进行处理.

    1
    2
    3
    public static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";
    mIntent.setComponent(new ComponentName(PrintManager.PRINT_SPOOLER_PACKAGE_NAME,
    PrintManager.PRINT_SPOOLER_PACKAGE_NAME + ".model.PrintSpoolerService"));

    以restartPrintJob为例. 说明下调用流程. (app调用PrintManager的接口)

    PrintManager –> PrintManagerService –> UserState – > RemotePrintSpooler –> RPS.SetPrintJobStateCaller–> PrintSpooler.PrintSpoolerService – setPrintJobState –> PrintSpooler.PrintSpoolerService – sendOnPrintJobQueued –> mClient.onPrintJobQueued(printJob);

    回调过程:

    PrintSpoolerClient.onPrintJobQueued –> UserState–onPrintJobQueued–> RemotePrintService.onPrintJobQueued–> 打印插件服务– onPrintJobQueued

    可见有最终任务的还是要通过打印插件服务传递给打印机.

4. 系统内建打印插件服务

BuiltInPrintService

packages/services/BuiltInPrintService/

4.1. Manifest 解释

1
2
3
<service android:name="com.android.bips.BuiltInPrintService"
<service android:name="com.android.bips.render.PdfRenderService"
android:name="com.android.bips.ui.AddPrintersActivity"
1
2
3
4
<print-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:addPrintersActivity="com.android.bips.ui.AddPrintersActivity"
/>

服务插件需要继承 PrintService

1
public class BuiltInPrintService extends PrintService {

继承的方法:

  • onCreatePrinterDiscoverySession
  • onRequestCancelPrintJob(PrintJob printJob)
  • onPrintJobQueued(PrintJob printJob)

4.2. PrintService 基类

PrintService是RemotePrintService bind的基类, RMS中保存的mPrintService指向该类

成员:

  • mClient

    指向RemotePrintService的内部类RemotePrintServiceClient.

    该变量被传到PrintJob的mPrintServiceClient中.

  • mDiscoverySession

    通过子类实现的onCreatePrinterDiscoverySession的方法创建.

    为PrinterDiscoverySession对象. 需要打印服务插件继承该类.提供打印插件内打印机搜索跟踪打印机状态等的功能.

4.3. PrinterDiscoverySession基类

服务插件的Session类需要继承PrinterDiscoverySession

需继承的方法:

  • onStartPrinterDiscovery(@NonNull List priorityList)

  • onStopPrinterDiscovery()

  • onValidatePrinters(@NonNull List printerIds)

  • onStartPrinterStateTracking(@NonNull PrinterId printerId)

  • onRequestCustomPrinterIcon

  • onStopPrinterStateTracking

  • onDestroy

5. Ui 显示

系统中内置的加载printer的显示为Settings进程.

packages/apps/Settings/src/com/android/settings/print/

PrintServiceSettingsFragment.java

涉及到LOADER的使用:

1
2
3
4
5
6
7
   public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
implements SwitchBar.OnSwitchChangeListener,
LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {

private final class PrintersAdapter extends BaseAdapter
implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable {

5.1. Loader

Loader在执行了startLoading()方法后,会进入started状态,LoaderManager会在合适的时机执行Loader.startLoading()方法,概括来说,当我们执行LoadManager.initLoader()时,如果Loader不存在,内部会执行LoadCallbacks的onCreateLoader()方法创建Loader,并让新创建的Loader执行startLoading()方法。

具体执行过程如下:
LoaderManager.initLoader() ->
LoaderManager.createAndInstallLoader() ->
LoaderManager.createLoader() ->
LoaderCallbacks.onCreateLoader() ->
得到loader之后创建LoaderInfo ->
LoaderManager.installLoader() ->
将其放入LoaderManager内部维护的mLoaders数组中 ->
LoaderInfo.start() ->
Loader处于started状态 ->
Loader.startLoading() ->Loader.onStartLoading()

5.2. LoaderManager.LoaderCallbacks

LoaderManager.LoaderCallbacks是LoaderManager中的内部接口,客户端与Loader的通信完全是事件机制,即客户端需要实现LoaderCallbacks中的各种回调方法,以响应Loader & LoaderManager触发的各种事件。客户端在调用LoaderManager的initLoader()或restartLoader()方法时,就需要客户端向这两个方法中传入一个LoaderCallbacks的实例。LoaderCallbacks有三个回调方法需要实现:onCreateLoader()、onLoadFinished()以及onLoaderReset()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
implements SwitchBar.OnSwitchChangeListener,
LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
// this 是 PrintServiceSettingsFragment
getLoaderManager().initLoader(LOADER_ID_PRINT_SERVICE_LOADER, null, this);
@Override
public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
return new PrintServicesLoader(
(PrintManager) getContext().getSystemService(Context.PRINT_SERVICE), getContext(),
PrintManager.ALL_SERVICES);
}


private final class PrintersAdapter extends BaseAdapter
implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable {
// this 是PrintAdapter
public void enable() {
getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
}

@Override
public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
if (id == LOADER_ID_PRINTERS_LOADER) {
return new PrintersLoader(getContext());
}
return null;
}

5.3. onCreateLoader

onCreateLoader:我们要在onCreateLoader()方法内返回一个Loader的实例对象。很多情况下,我们需要查询ContentProvider里面的内容,那么我们就需要在onCreateLoader中返回一个CursorLoader的实例,CursorLoader继承自Loader。

如果CursorLoader不能满足我们的需求,我们可以自己编写自己的Loader然后在此onCreateLoader方法中返回。

此处是自己构造的loader

1
public class PrintServicesLoader extends Loader<List<PrintServiceInfo>>

此处返回的是Loader<List>, 是PrintServicesLoader对象.

PrintServiceInfo是关联到安装的打印插件服务的. PrintServiceInfo中保存了打印服务插件的从PackageManager拿到的resolveInfo信息(queryIntentServicesAsUser返回的结果)和前面介绍的settingsActivityName/addPrintersActivityName/advancedPrintOptionsActivityName

1
2
3
4
//readInstalledPrintServicesLocked方法中添加的PrintServiceInfo
tempPrintServices.add(PrintServiceInfo.create(mContext, installedService));
mInstalledServices.addAll(tempPrintServices);
//通过PrintManager getPrintServices拿到的就是mInstalledServices集合
1
2
3
4
5
6
7
8
public PrintServicesLoader(@NonNull PrintManager printManager, @NonNull Context context,
int selectionFlags) {
super(Preconditions.checkNotNull(context));
mHandler = new MyHandler();
mPrintManager = Preconditions.checkNotNull(printManager);
mSelectionFlags = Preconditions.checkFlagsArgument(selectionFlags,
PrintManager.ALL_SERVICES);
}

onForceLoad

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Override
protected void onForceLoad() {
queueNewResult();
}

/**
* Read the print services and queue it to be delivered on the main thread.
*/
private void queueNewResult() {
Message m = mHandler.obtainMessage(0);
1. // 此处就是调用mPrintManager.getPrintServices(PrintManager.ALL_SERVICES);拿到所有安装的打印插件
m.obj = mPrintManager.getPrintServices(mSelectionFlags);
mHandler.sendMessage(m);
}

private class MyHandler extends Handler {
/**
* Create a new handler on the main thread.
*/
public MyHandler() {
super(getContext().getMainLooper());
}

@Override
public void handleMessage(Message msg) {
if (isStarted()) {
2. 通知loader更新,回调LoadCallbacks.onLoadFinished()
deliverResult((List<PrintServiceInfo>) msg.obj);
}
}
}

在回调onPrintServiceChanged时也进行更新

1
2
3
4
5
6
7
mListener = new PrintManager.PrintServicesChangeListener() {
@Override public void onPrintServicesChanged() {
queueNewResult();
}
};

mPrintManager.addPrintServicesChangeListener(mListener, null);

我们可以在onStartLoading()中写我们的逻辑,在started状态下,Loader应该监控数据源的变化,并将新数据发送给客户端,具体来说就是当监控到新数据后,调用Loader.deliverResult()方法,触发LoadCallbacks.onLoadFinished()回调的执行,从而客户端可以从该回调中轻松获取数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
List<PrintServiceInfo> services) {
if (services != null) {
final int numServices = services.size();
for (int i = 0; i < numServices; i++) {
if (services.get(i).getComponentName().equals(mComponentName)) {
service = services.get(i);
break;
}
}
}
// enable状态是根据是否在mActiveServices中
// installedService.setIsEnabled(mActiveServices.containsKey(componentName));
1. mServiceEnabled = service.isEnabled();
2. ...//获取当前service的mSettingsIntent和mAddPrintersIntent对应打印插件的settingsActivityName/addPrintersActivityName
3. updateUiForServiceState()

3. private void updateUiForServiceState() {
// 根据mServiceEnabled控制按钮的开关
if (mServiceEnabled) {
mSwitchBar.setCheckedInternal(true);
mPrintersAdapter.enable();
} else {
mSwitchBar.setCheckedInternal(false);
mPrintersAdapter.disable();
}
getActivity().invalidateOptionsMenu();
}
3.1 mPrintersAdapter.enable();
public void enable() {
getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
}

在最后调用了PrintAdapter的initLoader方法, 该方法会触发onCreateLoader的回调.PrintAdapter对应的Loader为PrintersLoader类.

1
2
3
4
5
6
7
@Override
public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
if (id == LOADER_ID_PRINTERS_LOADER) {
return new PrintersLoader(getContext());
}
return null;
}

PrintersLoader重写了Loader中的onStartLoading()方法,以下是PrintersLoader在执行到onStartLoading()之后的逻辑,从中我们可以看出PrintLoader如何实现异步加载打印机数据。

在onForceLoad中执行了AsyncTask启动startPrinterDiscovery进行搜索搜索打印插件关联的打印机, 在搜索到打印机后,由callback机制, 回调注册的OnPrintersChangeListener的onPrintersChanged方法, 通过deliverResult触发LoaderCallbacks的onLoadFinished方法, 再通过notifyDataSetChanged方法使得视图更新.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@Override
protected void onStartLoading() {
if (DEBUG) {
Log.i(LOG_TAG, "onStartLoading()");
}
// The contract is that if we already have a valid,
// result the we have to deliver it immediately.
if (!mPrinters.isEmpty()) {
//触发PrintAdapter的onLoadFinished回调
2. deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
}
// We want to start discovery at this point.
1. onForceLoad();
}

1. protected void onForceLoad() {
loadInternal();
}

private void loadInternal() {
if (mDiscoverySession == null) {
PrintManager printManager = (PrintManager) getContext()
.getSystemService(Context.PRINT_SERVICE);
//SPRD 742355 main thread block by binder caused anr
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
//启动搜索打印机的服务 对应BuiltInPrintService 为 LocalDiscoverySession.
// 这个地方是通过PrintManager-->PrintManagerService-->UserState-->UserState.PrinterDiscoverySessionMediator-->(通过mActiveServices遍历到所有激活的)RemotePrintService-->打印插件的session.
mDiscoverySession = printManager.createPrinterDiscoverySession();
return null;
}
@Override
protected void onPostExecute(Void result) {
// 搜索到打印机后触发的回调
mDiscoverySession.setOnPrintersChangeListener(new OnPrintersChangeListener() {
@Override
public void onPrintersChanged() {
// 触发PrintAdapter onLoadFinished回调
deliverResult(new ArrayList<PrinterInfo>(
mDiscoverySession.getPrinters()));
}
});
//开始搜索打印插件关联的打印机,也是最终传到打印插件的Session
mDiscoverySession.startPrinterDiscovery(null);
}

}.execute();

}

2. public void onLoadFinished(Loader<List<PrinterInfo>> loader,
List<PrinterInfo> printers) {
synchronized (mLock) {
mPrinters.clear();
final int printerCount = printers.size();
for (int i = 0; i < printerCount; i++) {
PrinterInfo printer = printers.get(i);
//只更新当前插件的
if (printer.getId().getServiceName().equals(mComponentName)) {
mPrinters.add(printer);
}
}
mFilteredPrinters.clear();
mFilteredPrinters.addAll(mPrinters);
if (!TextUtils.isEmpty(mLastSearchString)) {
getFilter().filter(mLastSearchString);
}
}
// 触发PrintAdapter的getView方法回调,根据更新的mPrinters列表更新视图.
notifyDataSetChanged();
}

5.4. destroyLoader

在由PrintServiceLoader注册的addPrintServicesChangeListener回调流程中,在检测到PrintService change时, 最终触发下面的流程.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   private void updateUiForServiceState() {
if (mServiceEnabled) {
mSwitchBar.setCheckedInternal(true);
mPrintersAdapter.enable();
} else {
// 对应该控件绑定的service关闭了
mSwitchBar.setCheckedInternal(false);
1. mPrintersAdapter.disable();
}
getActivity().invalidateOptionsMenu();
}
1. public void disable() {
getLoaderManager().destroyLoader(LOADER_ID_PRINTERS_LOADER);
mPrinters.clear();
}

LoaderManager.destroy() –>

LoaderCallbacks.onLoaderReset() –>

Loader.reset() –>

PrintLoader.onReset()–>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//回调PrintAdapter的onLoaderReset, 更新视图,去除显示的打印机.
@Override
public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
synchronized (mLock) {
mPrinters.clear();
mFilteredPrinters.clear();
mLastSearchString = null;
}
notifyDataSetInvalidated();
}
// 回调PrintLoader的onReset
@Override
protected void onReset() {
if (DEBUG) {
Log.i(LOG_TAG, "onReset()");
}
1. onStopLoading();
mPrinters.clear();
if (mDiscoverySession != null) {
2. mDiscoverySession.destroy();
mDiscoverySession = null;
}
}
1. protected void onStopLoading() {
if (DEBUG) {
Log.i(LOG_TAG, "onStopLoading()");
}
onCancelLoad();
}
protected boolean onCancelLoad() {
if (DEBUG) {
Log.i(LOG_TAG, "onCancelLoad()");
}
return cancelInternal();
}
private boolean cancelInternal() {
if (mDiscoverySession != null
&& mDiscoverySession.isPrinterDiscoveryStarted()) {
// 停止搜索, 注意这个地方是停止所有active 打印service绑定session的搜索.
1.1 mDiscoverySession.stopPrinterDiscovery();
return true;
}
return false;
}