blob: 10cc7715c59940d2eff9b9aa518e00be60383d81 [file] [log] [blame]
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.print;
18
19import android.content.Context;
20import android.content.IntentSender;
21import android.content.IntentSender.SendIntentException;
Svetoslav62836082013-07-17 14:52:35 -070022import android.os.Bundle;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070023import android.os.CancellationSignal;
24import android.os.Handler;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070025import android.os.Looper;
26import android.os.Message;
27import android.os.ParcelFileDescriptor;
28import android.os.RemoteException;
Svetoslav Ganova0027152013-06-25 14:59:53 -070029import android.print.PrintDocumentAdapter.LayoutResultCallback;
30import android.print.PrintDocumentAdapter.WriteResultCallback;
Svetoslav Ganov860f8a62013-09-14 00:59:03 -070031import android.printservice.PrintServiceInfo;
Svetoslav Ganov88d19912013-07-22 12:32:03 -070032import android.text.TextUtils;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070033import android.util.Log;
34
35import com.android.internal.os.SomeArgs;
36
37import libcore.io.IoUtils;
38
39import java.io.File;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070040import java.lang.ref.WeakReference;
41import java.util.ArrayList;
42import java.util.Collections;
43import java.util.List;
44
45/**
46 * System level service for accessing the printing capabilities of the platform.
47 * <p>
48 * To obtain a handle to the print manager do the following:
49 * </p>
50 * <pre>
51 * PrintManager printManager =
52 * (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
53 * </pre>
54 */
55public final class PrintManager {
56
57 private static final String LOG_TAG = "PrintManager";
58
59 /** @hide */
60 public static final int APP_ID_ANY = -2;
61
62 private final Context mContext;
63
64 private final IPrintManager mService;
65
66 private final int mUserId;
67
68 private final int mAppId;
69
70 private final PrintClient mPrintClient;
71
72 private final Handler mHandler;
73
74 /**
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070075 * Creates a new instance.
76 *
77 * @param context The current context in which to operate.
78 * @param service The backing system service.
79 *
80 * @hide
81 */
82 public PrintManager(Context context, IPrintManager service, int userId, int appId) {
83 mContext = context;
84 mService = service;
85 mUserId = userId;
86 mAppId = appId;
87 mPrintClient = new PrintClient(this);
88 mHandler = new Handler(context.getMainLooper(), null, false) {
89 @Override
90 public void handleMessage(Message message) {
91 SomeArgs args = (SomeArgs) message.obj;
92 Context context = (Context) args.arg1;
93 IntentSender intent = (IntentSender) args.arg2;
94 args.recycle();
95 try {
96 context.startIntentSender(intent, null, 0, 0, 0);
97 } catch (SendIntentException sie) {
98 Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
99 }
100 }
101 };
102 }
103
104 /**
105 * Creates an instance that can access all print jobs.
106 *
107 * @param userId The user id for which to get all print jobs.
Svetoslav Ganova0027152013-06-25 14:59:53 -0700108 * @return An instance if the caller has the permission to access
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700109 * all print jobs, null otherwise.
110 *
111 * @hide
112 */
113 public PrintManager getGlobalPrintManagerForUser(int userId) {
114 return new PrintManager(mContext, mService, userId, APP_ID_ANY);
115 }
116
Svetoslav Ganova0027152013-06-25 14:59:53 -0700117 PrintJobInfo getPrintJobInfo(int printJobId) {
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700118 try {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700119 return mService.getPrintJobInfo(printJobId, mAppId, mUserId);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700120 } catch (RemoteException re) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700121 Log.e(LOG_TAG, "Error getting a print job info:" + printJobId, re);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700122 }
123 return null;
124 }
125
126 /**
127 * Gets the print jobs for this application.
128 *
129 * @return The print job list.
130 *
131 * @see PrintJob
132 */
133 public List<PrintJob> getPrintJobs() {
134 try {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700135 List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700136 if (printJobInfos == null) {
137 return Collections.emptyList();
138 }
139 final int printJobCount = printJobInfos.size();
140 List<PrintJob> printJobs = new ArrayList<PrintJob>(printJobCount);
141 for (int i = 0; i < printJobCount; i++) {
142 printJobs.add(new PrintJob(printJobInfos.get(i), this));
143 }
144 return printJobs;
145 } catch (RemoteException re) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700146 Log.e(LOG_TAG, "Error getting print jobs", re);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700147 }
148 return Collections.emptyList();
149 }
150
Svetoslav Ganova0027152013-06-25 14:59:53 -0700151 void cancelPrintJob(int printJobId) {
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700152 try {
153 mService.cancelPrintJob(printJobId, mAppId, mUserId);
154 } catch (RemoteException re) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700155 Log.e(LOG_TAG, "Error cancleing a print job: " + printJobId, re);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700156 }
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700157 }
158
159 /**
160 * Creates a print job for printing a file with default print attributes.
161 *
162 * @param printJobName A name for the new print job.
163 * @param pdfFile The PDF file to print.
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700164 * @param documentInfo Information about the printed document.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700165 * @param attributes The default print job attributes.
Svetoslav Ganovd26d4892013-08-28 14:37:54 -0700166 * @return The created print job on success or null on failure.
Svetoslavfd906512013-06-24 09:04:48 -0700167 *
168 * @see PrintJob
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700169 */
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700170 public PrintJob print(String printJobName, File pdfFile, PrintDocumentInfo documentInfo,
171 PrintAttributes attributes) {
172 PrintFileDocumentAdapter documentAdapter = new PrintFileDocumentAdapter(
173 mContext, pdfFile, documentInfo);
Svetoslav Ganova0027152013-06-25 14:59:53 -0700174 return print(printJobName, documentAdapter, attributes);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700175 }
176
177 /**
Svetoslav Ganova0027152013-06-25 14:59:53 -0700178 * Creates a print job for printing a {@link PrintDocumentAdapter} with default print
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700179 * attributes.
180 *
181 * @param printJobName A name for the new print job.
Svetoslav Ganova0027152013-06-25 14:59:53 -0700182 * @param documentAdapter An adapter that emits the document to print.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700183 * @param attributes The default print job attributes.
Svetoslav Ganovd26d4892013-08-28 14:37:54 -0700184 * @return The created print job on success or null on failure.
Svetoslavfd906512013-06-24 09:04:48 -0700185 *
186 * @see PrintJob
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700187 */
Svetoslav Ganova0027152013-06-25 14:59:53 -0700188 public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter,
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700189 PrintAttributes attributes) {
Svetoslav Ganov88d19912013-07-22 12:32:03 -0700190 if (TextUtils.isEmpty(printJobName)) {
191 throw new IllegalArgumentException("priintJobName cannot be empty");
192 }
Svetoslav Ganova0027152013-06-25 14:59:53 -0700193 PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(documentAdapter,
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700194 mContext.getMainLooper());
195 try {
196 PrintJobInfo printJob = mService.print(printJobName, mPrintClient, delegate,
197 attributes, mAppId, mUserId);
198 if (printJob != null) {
199 return new PrintJob(printJob, this);
200 }
201 } catch (RemoteException re) {
202 Log.e(LOG_TAG, "Error creating a print job", re);
203 }
204 return null;
205 }
206
Svetoslav Ganov44720af2013-08-20 16:32:53 -0700207 /**
Svetoslav Ganov860f8a62013-09-14 00:59:03 -0700208 * Gets the list of enabled print services.
209 *
210 * @return The enabled service list or an empty list.
211 *
212 * @hide
213 */
214 public List<PrintServiceInfo> getEnabledPrintServices() {
215 try {
216 List<PrintServiceInfo> enabledServices = mService.getEnabledPrintServices(mUserId);
217 if (enabledServices != null) {
218 return enabledServices;
219 }
220 } catch (RemoteException re) {
221 Log.e(LOG_TAG, "Error getting the enalbed print services", re);
222 }
223 return Collections.emptyList();
224 }
225
226 /**
Svetoslav Ganov44720af2013-08-20 16:32:53 -0700227 * @hide
228 */
229 public PrinterDiscoverySession createPrinterDiscoverySession() {
230 return new PrinterDiscoverySession(mService, mContext, mUserId);
231 }
232
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700233 private static final class PrintClient extends IPrintClient.Stub {
234
235 private final WeakReference<PrintManager> mWeakPrintManager;
236
237 public PrintClient(PrintManager manager) {
238 mWeakPrintManager = new WeakReference<PrintManager>(manager);
239 }
240
241 @Override
242 public void startPrintJobConfigActivity(IntentSender intent) {
243 PrintManager manager = mWeakPrintManager.get();
244 if (manager != null) {
245 SomeArgs args = SomeArgs.obtain();
246 args.arg1 = manager.mContext;
247 args.arg2 = intent;
248 manager.mHandler.obtainMessage(0, args).sendToTarget();
249 }
250 }
251 }
252
Svetoslav Ganova0027152013-06-25 14:59:53 -0700253 private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub {
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700254
255 private final Object mLock = new Object();
256
257 private CancellationSignal mLayoutOrWriteCancellation;
258
Svetoslav Ganova0027152013-06-25 14:59:53 -0700259 private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in finish()
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700260
Svetoslav Ganova0027152013-06-25 14:59:53 -0700261 private Handler mHandler; // Strong reference OK - cleared in finish()
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700262
Svetoslav Ganova0027152013-06-25 14:59:53 -0700263 public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) {
264 mDocumentAdapter = documentAdapter;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700265 mHandler = new MyHandler(looper);
266 }
267
268 @Override
269 public void start() {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700270 mHandler.sendEmptyMessage(MyHandler.MSG_START);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700271 }
272
273 @Override
Svetoslav62836082013-07-17 14:52:35 -0700274 public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700275 ILayoutResultCallback callback, Bundle metadata, int sequence) {
276 synchronized (mLock) {
277 if (mLayoutOrWriteCancellation != null) {
278 mLayoutOrWriteCancellation.cancel();
279 }
280 }
Svetoslav Ganova0027152013-06-25 14:59:53 -0700281 SomeArgs args = SomeArgs.obtain();
282 args.arg1 = oldAttributes;
283 args.arg2 = newAttributes;
284 args.arg3 = callback;
Svetoslav62836082013-07-17 14:52:35 -0700285 args.arg4 = metadata;
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700286 args.argi1 = sequence;
287 mHandler.removeMessages(MyHandler.MSG_LAYOUT);
Svetoslav Ganova0027152013-06-25 14:59:53 -0700288 mHandler.obtainMessage(MyHandler.MSG_LAYOUT, args).sendToTarget();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700289 }
290
291 @Override
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700292 public void write(PageRange[] pages, ParcelFileDescriptor fd,
293 IWriteResultCallback callback, int sequence) {
294 synchronized (mLock) {
295 if (mLayoutOrWriteCancellation != null) {
296 mLayoutOrWriteCancellation.cancel();
297 }
298 }
Svetoslav Ganova0027152013-06-25 14:59:53 -0700299 SomeArgs args = SomeArgs.obtain();
300 args.arg1 = pages;
Svetoslav Ganovd26d4892013-08-28 14:37:54 -0700301 args.arg2 = fd;
Svetoslav Ganova0027152013-06-25 14:59:53 -0700302 args.arg3 = callback;
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700303 args.argi1 = sequence;
304 mHandler.removeMessages(MyHandler.MSG_WRITE);
Svetoslav Ganova0027152013-06-25 14:59:53 -0700305 mHandler.obtainMessage(MyHandler.MSG_WRITE, args).sendToTarget();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700306 }
307
308 @Override
309 public void finish() {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700310 mHandler.sendEmptyMessage(MyHandler.MSG_FINISH);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700311 }
312
Svetoslav Ganova0027152013-06-25 14:59:53 -0700313 private boolean isFinished() {
314 return mDocumentAdapter == null;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700315 }
316
Svetoslav Ganova0027152013-06-25 14:59:53 -0700317 private void doFinish() {
318 mDocumentAdapter = null;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700319 mHandler = null;
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700320 mLayoutOrWriteCancellation = null;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700321 }
322
323 private final class MyHandler extends Handler {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700324 public static final int MSG_START = 1;
325 public static final int MSG_LAYOUT = 2;
326 public static final int MSG_WRITE = 3;
327 public static final int MSG_FINISH = 4;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700328
329 public MyHandler(Looper looper) {
330 super(looper, null, true);
331 }
332
333 @Override
334 public void handleMessage(Message message) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700335 if (isFinished()) {
336 return;
337 }
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700338 switch (message.what) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700339 case MSG_START: {
340 mDocumentAdapter.onStart();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700341 } break;
342
Svetoslav Ganova0027152013-06-25 14:59:53 -0700343 case MSG_LAYOUT: {
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700344 SomeArgs args = (SomeArgs) message.obj;
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700345 PrintAttributes oldAttributes = (PrintAttributes) args.arg1;
346 PrintAttributes newAttributes = (PrintAttributes) args.arg2;
347 ILayoutResultCallback callback = (ILayoutResultCallback) args.arg3;
348 Bundle metadata = (Bundle) args.arg4;
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700349 final int sequence = args.argi1;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700350 args.recycle();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700351
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700352 CancellationSignal cancellation = new CancellationSignal();
353 synchronized (mLock) {
354 mLayoutOrWriteCancellation = cancellation;
Svetoslav Ganova0027152013-06-25 14:59:53 -0700355 }
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700356
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700357 mDocumentAdapter.onLayout(oldAttributes, newAttributes, cancellation,
358 new MyLayoutResultCallback(callback, sequence), metadata);
Svetoslav Ganova0027152013-06-25 14:59:53 -0700359 } break;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700360
Svetoslav Ganova0027152013-06-25 14:59:53 -0700361 case MSG_WRITE: {
362 SomeArgs args = (SomeArgs) message.obj;
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700363 PageRange[] pages = (PageRange[]) args.arg1;
Svetoslav Ganovd26d4892013-08-28 14:37:54 -0700364 ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg2;
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700365 IWriteResultCallback callback = (IWriteResultCallback) args.arg3;
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700366 final int sequence = args.argi1;
Svetoslav Ganova0027152013-06-25 14:59:53 -0700367 args.recycle();
368
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700369 CancellationSignal cancellation = new CancellationSignal();
370 synchronized (mLock) {
371 mLayoutOrWriteCancellation = cancellation;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700372 }
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700373
374 mDocumentAdapter.onWrite(pages, fd, cancellation,
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700375 new MyWriteResultCallback(callback, fd, sequence));
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700376 } break;
377
Svetoslav Ganova0027152013-06-25 14:59:53 -0700378 case MSG_FINISH: {
379 mDocumentAdapter.onFinish();
380 doFinish();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700381 } break;
382
383 default: {
384 throw new IllegalArgumentException("Unknown message: "
385 + message.what);
386 }
387 }
388 }
389 }
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700390
391 private final class MyLayoutResultCallback extends LayoutResultCallback {
392 private ILayoutResultCallback mCallback;
393 private final int mSequence;
394
395 public MyLayoutResultCallback(ILayoutResultCallback callback,
396 int sequence) {
397 mCallback = callback;
398 mSequence = sequence;
399 }
400
401 @Override
402 public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
Svetoslav269403b2013-08-14 17:31:04 -0700403 if (info == null) {
404 throw new NullPointerException("document info cannot be null");
405 }
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700406 final ILayoutResultCallback callback;
407 synchronized (mLock) {
408 callback = mCallback;
409 clearLocked();
410 }
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700411 if (callback != null) {
412 try {
413 callback.onLayoutFinished(info, changed, mSequence);
414 } catch (RemoteException re) {
415 Log.e(LOG_TAG, "Error calling onLayoutFinished", re);
416 }
417 }
418 }
419
420 @Override
421 public void onLayoutFailed(CharSequence error) {
422 final ILayoutResultCallback callback;
423 synchronized (mLock) {
424 callback = mCallback;
425 clearLocked();
426 }
427 if (callback != null) {
428 try {
429 callback.onLayoutFailed(error, mSequence);
430 } catch (RemoteException re) {
431 Log.e(LOG_TAG, "Error calling onLayoutFailed", re);
432 }
433 }
434 }
435
436 @Override
437 public void onLayoutCancelled() {
438 synchronized (mLock) {
439 clearLocked();
440 }
441 }
442
443 private void clearLocked() {
444 mLayoutOrWriteCancellation = null;
445 mCallback = null;
446 }
447 }
448
449 private final class MyWriteResultCallback extends WriteResultCallback {
Svetoslav Ganovd26d4892013-08-28 14:37:54 -0700450 private ParcelFileDescriptor mFd;
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700451 private int mSequence;
452 private IWriteResultCallback mCallback;
453
454 public MyWriteResultCallback(IWriteResultCallback callback,
Svetoslav Ganovd26d4892013-08-28 14:37:54 -0700455 ParcelFileDescriptor fd, int sequence) {
Svetoslav Ganov14db9652013-08-06 14:40:46 -0700456 mFd = fd;
457 mSequence = sequence;
458 mCallback = callback;
459 }
460
461 @Override
462 public void onWriteFinished(PageRange[] pages) {
463 final IWriteResultCallback callback;
464 synchronized (mLock) {
465 callback = mCallback;
466 clearLocked();
467 }
468 if (pages == null) {
469 throw new IllegalArgumentException("pages cannot be null");
470 }
471 if (pages.length == 0) {
472 throw new IllegalArgumentException("pages cannot be empty");
473 }
474 if (callback != null) {
475 try {
476 callback.onWriteFinished(pages, mSequence);
477 } catch (RemoteException re) {
478 Log.e(LOG_TAG, "Error calling onWriteFinished", re);
479 }
480 }
481 }
482
483 @Override
484 public void onWriteFailed(CharSequence error) {
485 final IWriteResultCallback callback;
486 synchronized (mLock) {
487 callback = mCallback;
488 clearLocked();
489 }
490 if (callback != null) {
491 try {
492 callback.onWriteFailed(error, mSequence);
493 } catch (RemoteException re) {
494 Log.e(LOG_TAG, "Error calling onWriteFailed", re);
495 }
496 }
497 }
498
499 @Override
500 public void onWriteCancelled() {
501 synchronized (mLock) {
502 clearLocked();
503 }
504 }
505
506 private void clearLocked() {
507 mLayoutOrWriteCancellation = null;
508 IoUtils.closeQuietly(mFd);
509 mCallback = null;
510 mFd = null;
511 }
512 }
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700513 }
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700514}