Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package android.print; |
| 18 | |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 19 | import android.os.Bundle; |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 20 | import android.os.CancellationSignal; |
Svetoslav Ganov | d26d489 | 2013-08-28 14:37:54 -0700 | [diff] [blame] | 21 | import android.os.ParcelFileDescriptor; |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 22 | |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 23 | /** |
| 24 | * Base class that provides the content of a document to be printed. |
| 25 | * |
| 26 | * <h3>Lifecycle</h3> |
| 27 | * <p> |
| 28 | * <ul> |
| 29 | * <li> |
| 30 | * Initially, you will receive a call to {@link #onStart()}. This callback |
| 31 | * can be used to allocate resources. |
| 32 | * </li> |
| 33 | * <li> |
| 34 | * Next, you will get one or more calls to {@link #onLayout(PrintAttributes, |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 35 | * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} to |
| 36 | * inform you that the print attributes (page size, density, etc) changed |
| 37 | * giving you an opportunity to layout the content to match the new constraints. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 38 | * </li> |
| 39 | * <li> |
| 40 | * After every call to {@link #onLayout(PrintAttributes, PrintAttributes, |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 41 | * CancellationSignal, LayoutResultCallback, Bundle)}, you <strong>may</strong> get |
| 42 | * a call to {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, |
| 43 | * WriteResultCallback)} asking you to write a PDF file with the content for |
| 44 | * specific pages. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 45 | * </li> |
| 46 | * <li> |
| 47 | * Finally, you will receive a call to {@link #onFinish()}. You can use this |
| 48 | * callback to release resources allocated in {@link #onStart()}. |
| 49 | * </li> |
| 50 | * </ul> |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 51 | * <p> |
| 52 | * The {@link #onStart()} callback is always the first call you will receive and |
| 53 | * is useful for doing one time setup or resource allocation before printing. You |
| 54 | * will not receive a subsequent call here. |
| 55 | * </p> |
| 56 | * <p> |
| 57 | * The {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal, |
| 58 | * LayoutResultCallback, Bundle)} callback requires that you layout the content |
| 59 | * based on the current {@link PrintAttributes}. The execution of this method is |
| 60 | * not considered completed until you invoke one of the methods on the passed in |
| 61 | * callback instance. Hence, you will not receive a subsequent call to any other |
| 62 | * method of this class until the execution of this method is complete by invoking |
| 63 | * one of the callback methods. |
| 64 | * </p> |
| 65 | * <p> |
| 66 | * The {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, |
| 67 | * WriteResultCallback)} requires that you render and write the content of some |
| 68 | * pages to the provided destination. The execution of this method is not |
| 69 | * considered complete until you invoke one of the methods on the passed in |
| 70 | * callback instance. Hence, you will not receive a subsequent call to any other |
| 71 | * method of this class until the execution of this method is complete by invoking |
| 72 | * one of the callback methods. You will never receive a sequence of one or more |
| 73 | * calls to this method without a previous call to {@link #onLayout(PrintAttributes, |
| 74 | * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)}. |
| 75 | * </p> |
| 76 | * <p> |
| 77 | * The {@link #onFinish()} callback is always the last call you will receive and |
| 78 | * is useful for doing one time cleanup or resource deallocation after printing. |
| 79 | * You will not receive a subsequent call here. |
| 80 | * </p> |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 81 | * </p> |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 82 | * <h3>Implementation</h3> |
| 83 | * <p> |
| 84 | * The APIs defined in this class are designed to enable doing part or all |
| 85 | * of the work on an arbitrary thread. For example, if the printed content |
| 86 | * does not depend on the UI state, i.e. on what is shown on the screen, then |
Svetoslav Ganov | 19fba5d | 2013-08-30 18:37:43 -0700 | [diff] [blame] | 87 | * you can offload the entire work on a dedicated thread, thus making your |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 88 | * application interactive while the print work is being performed. Note that |
| 89 | * while your activity is covered by the system print UI and a user cannot |
| 90 | * interact with it, doing the printing work on the main application thread |
| 91 | * may affect the performance of your other application components as they |
| 92 | * are also executed on that thread. |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 93 | * </p> |
| 94 | * <p> |
| 95 | * You can also do work on different threads, for example if you print UI |
| 96 | * content, you can handle {@link #onStart()} and {@link #onLayout(PrintAttributes, |
| 97 | * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} on |
| 98 | * the UI thread (assuming onStart initializes resources needed for layout). |
| 99 | * This will ensure that the UI does not change while you are laying out the |
Svetoslav Ganov | d26d489 | 2013-08-28 14:37:54 -0700 | [diff] [blame] | 100 | * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor, |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 101 | * CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 102 | * thread. This will ensure that the main thread is busy for a minimal amount of |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 103 | * time. Also this assumes that you will generate the printed content in |
| 104 | * {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal, |
| 105 | * LayoutResultCallback, Bundle)} which is not mandatory. If you use multiple |
| 106 | * threads, you are responsible for proper synchronization. |
| 107 | * </p> |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 108 | */ |
| 109 | public abstract class PrintDocumentAdapter { |
| 110 | |
| 111 | /** |
Svetoslav | 6811f4e | 2013-09-18 15:58:28 -0700 | [diff] [blame] | 112 | * Extra: mapped to a boolean value that is <code>true</code> if |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 113 | * the current layout is for a print preview, <code>false</code> otherwise. |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 114 | * This extra is provided in the {@link Bundle} argument of the {@link |
| 115 | * #onLayout(PrintAttributes, PrintAttributes, CancellationSignal, |
| 116 | * LayoutResultCallback, Bundle)} callback. |
| 117 | * |
| 118 | * @see #onLayout(PrintAttributes, PrintAttributes, CancellationSignal, |
| 119 | * LayoutResultCallback, Bundle) |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 120 | */ |
Svetoslav | 6811f4e | 2013-09-18 15:58:28 -0700 | [diff] [blame] | 121 | public static final String EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW"; |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 122 | |
| 123 | /** |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 124 | * Called when printing starts. You can use this callback to allocate |
| 125 | * resources. This method is invoked on the main thread. |
| 126 | */ |
| 127 | public void onStart() { |
| 128 | /* do nothing - stub */ |
| 129 | } |
| 130 | |
| 131 | /** |
| 132 | * Called when the print attributes (page size, density, etc) changed |
| 133 | * giving you a chance to layout the content such that it matches the |
| 134 | * new constraints. This method is invoked on the main thread. |
| 135 | * <p> |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 136 | * After you are done laying out, you <strong>must</strong> invoke: {@link |
| 137 | * LayoutResultCallback#onLayoutFinished(PrintDocumentInfo, boolean)} with |
| 138 | * the last argument <code>true</code> or <code>false</code> depending on |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 139 | * whether the layout changed the content or not, respectively; or {@link |
| 140 | * LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred; |
| 141 | * or {@link LayoutResultCallback#onLayoutCancelled()} if layout was |
| 142 | * cancelled in a response to a cancellation request via the passed in |
| 143 | * {@link CancellationSignal}. Note that you <strong>must</strong> call one of |
Svetoslav | 57b296f | 2013-11-12 16:20:55 -0800 | [diff] [blame] | 144 | * the methods of the given callback for this method to be considered complete |
| 145 | * which is you will not receive any calls to this adapter until the current |
| 146 | * layout operation is complete by invoking a method on the callback instance. |
| 147 | * The callback methods can be invoked from an arbitrary thread. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 148 | * </p> |
| 149 | * <p> |
Svetoslav | 57b296f | 2013-11-12 16:20:55 -0800 | [diff] [blame] | 150 | * One of the arguments passed to this method is a {@link CancellationSignal} |
| 151 | * which is used to propagate requests from the system to your application for |
| 152 | * canceling the current layout operation. For example, a cancellation may be |
| 153 | * requested if the user changes a print option that may affect layout while |
| 154 | * you are performing a layout operation. In such a case the system will make |
| 155 | * an attempt to cancel the current layout as another one will have to be performed. |
| 156 | * Typically, you should register a cancellation callback in the cancellation |
| 157 | * signal. The cancellation callback <strong>will not</strong> be made on the |
| 158 | * main thread and can be registered as follows: |
| 159 | * </p> |
| 160 | * <pre> |
| 161 | * cancellationSignal.setOnCancelListener(new OnCancelListener() { |
| 162 | * @Override |
| 163 | * public void onCancel() { |
| 164 | * // Cancel layout |
| 165 | * } |
| 166 | * }); |
| 167 | * </pre> |
| 168 | * <p> |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 169 | * <strong>Note:</strong> If the content is large and a layout will be |
| 170 | * performed, it is a good practice to schedule the work on a dedicated |
| 171 | * thread and register an observer in the provided {@link |
| 172 | * CancellationSignal} upon invocation of which you should stop the |
Svetoslav | 57b296f | 2013-11-12 16:20:55 -0800 | [diff] [blame] | 173 | * layout. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 174 | * </p> |
| 175 | * |
| 176 | * @param oldAttributes The old print attributes. |
| 177 | * @param newAttributes The new print attributes. |
| 178 | * @param cancellationSignal Signal for observing cancel layout requests. |
| 179 | * @param callback Callback to inform the system for the layout result. |
Svetoslav | 6811f4e | 2013-09-18 15:58:28 -0700 | [diff] [blame] | 180 | * @param extras Additional information about how to layout the content. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 181 | * |
| 182 | * @see LayoutResultCallback |
| 183 | * @see CancellationSignal |
Svetoslav | 6811f4e | 2013-09-18 15:58:28 -0700 | [diff] [blame] | 184 | * @see #EXTRA_PRINT_PREVIEW |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 185 | */ |
| 186 | public abstract void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 187 | CancellationSignal cancellationSignal, LayoutResultCallback callback, |
Svetoslav | 6811f4e | 2013-09-18 15:58:28 -0700 | [diff] [blame] | 188 | Bundle extras); |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 189 | |
| 190 | /** |
| 191 | * Called when specific pages of the content should be written in the |
Svetoslav Ganov | 19fba5d | 2013-08-30 18:37:43 -0700 | [diff] [blame] | 192 | * form of a PDF file to the given file descriptor. This method is invoked |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 193 | * on the main thread. |
| 194 | *<p> |
Svetoslav Ganov | d26d489 | 2013-08-28 14:37:54 -0700 | [diff] [blame] | 195 | * After you are done writing, you should close the file descriptor and |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 196 | * invoke {@link WriteResultCallback#onWriteFinished(PageRange[])}, if writing |
Svetoslav Ganov | d26d489 | 2013-08-28 14:37:54 -0700 | [diff] [blame] | 197 | * completed successfully; or {@link WriteResultCallback#onWriteFailed( |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 198 | * CharSequence)}, if an error occurred; or {@link WriteResultCallback#onWriteCancelled()}, |
| 199 | * if writing was cancelled in a response to a cancellation request via the passed |
| 200 | * in {@link CancellationSignal}. Note that you <strong>must</strong> call one of |
Svetoslav | 57b296f | 2013-11-12 16:20:55 -0800 | [diff] [blame] | 201 | * the methods of the given callback for this method to be considered complete which |
| 202 | * is you will not receive any calls to this adapter until the current write |
| 203 | * operation is complete by invoking a method on the callback instance. The callback |
| 204 | * methods can be invoked from an arbitrary thread. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 205 | * </p> |
| 206 | * <p> |
Svetoslav | 57b296f | 2013-11-12 16:20:55 -0800 | [diff] [blame] | 207 | * One of the arguments passed to this method is a {@link CancellationSignal} |
| 208 | * which is used to propagate requests from the system to your application for |
| 209 | * canceling the current write operation. For example, a cancellation may be |
| 210 | * requested if the user changes a print option that may affect layout while |
| 211 | * you are performing a write operation. In such a case the system will make |
| 212 | * an attempt to cancel the current write as a layout will have to be performed |
| 213 | * which then may be followed by a write. Typically, you should register a |
| 214 | * cancellation callback in the cancellation signal. The cancellation callback |
| 215 | * <strong>will not</strong> be made on the main thread and can be registered |
| 216 | * as follows: |
| 217 | * </p> |
| 218 | * <pre> |
| 219 | * cancellationSignal.setOnCancelListener(new OnCancelListener() { |
| 220 | * @Override |
| 221 | * public void onCancel() { |
| 222 | * // Cancel write |
| 223 | * } |
| 224 | * }); |
| 225 | * </pre> |
| 226 | * <p> |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 227 | * <strong>Note:</strong> If the printed content is large, it is a good |
| 228 | * practice to schedule writing it on a dedicated thread and register an |
| 229 | * observer in the provided {@link CancellationSignal} upon invocation of |
Svetoslav | 57b296f | 2013-11-12 16:20:55 -0800 | [diff] [blame] | 230 | * which you should stop writing. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 231 | * </p> |
| 232 | * |
Svetoslav Ganov | 85b1f88 | 2013-07-24 17:00:06 -0700 | [diff] [blame] | 233 | * @param pages The pages whose content to print - non-overlapping in ascending order. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 234 | * @param destination The destination file descriptor to which to write. |
| 235 | * @param cancellationSignal Signal for observing cancel writing requests. |
| 236 | * @param callback Callback to inform the system for the write result. |
| 237 | * |
| 238 | * @see WriteResultCallback |
| 239 | * @see CancellationSignal |
| 240 | */ |
Svetoslav Ganov | d26d489 | 2013-08-28 14:37:54 -0700 | [diff] [blame] | 241 | public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination, |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 242 | CancellationSignal cancellationSignal, WriteResultCallback callback); |
| 243 | |
| 244 | /** |
| 245 | * Called when printing finishes. You can use this callback to release |
| 246 | * resources acquired in {@link #onStart()}. This method is invoked on |
| 247 | * the main thread. |
| 248 | */ |
| 249 | public void onFinish() { |
| 250 | /* do nothing - stub */ |
| 251 | } |
| 252 | |
| 253 | /** |
| 254 | * Base class for implementing a callback for the result of {@link |
Svetoslav Ganov | d26d489 | 2013-08-28 14:37:54 -0700 | [diff] [blame] | 255 | * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 256 | * WriteResultCallback)}. |
| 257 | */ |
| 258 | public static abstract class WriteResultCallback { |
| 259 | |
| 260 | /** |
| 261 | * @hide |
| 262 | */ |
| 263 | public WriteResultCallback() { |
| 264 | /* do nothing - hide constructor */ |
| 265 | } |
| 266 | |
| 267 | /** |
| 268 | * Notifies that all the data was written. |
| 269 | * |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 270 | * @param pages The pages that were written. Cannot be <code>null</code> |
| 271 | * or empty. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 272 | */ |
Svetoslav Ganov | 85b1f88 | 2013-07-24 17:00:06 -0700 | [diff] [blame] | 273 | public void onWriteFinished(PageRange[] pages) { |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 274 | /* do nothing - stub */ |
| 275 | } |
| 276 | |
| 277 | /** |
| 278 | * Notifies that an error occurred while writing the data. |
| 279 | * |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 280 | * @param error The <strong>localized</strong> error message. |
| 281 | * shown to the user. May be <code>null</code> if error is unknown. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 282 | */ |
| 283 | public void onWriteFailed(CharSequence error) { |
| 284 | /* do nothing - stub */ |
| 285 | } |
Svetoslav Ganov | 85b1f88 | 2013-07-24 17:00:06 -0700 | [diff] [blame] | 286 | |
| 287 | /** |
| 288 | * Notifies that write was cancelled as a result of a cancellation request. |
| 289 | */ |
| 290 | public void onWriteCancelled() { |
| 291 | /* do nothing - stub */ |
| 292 | } |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 293 | } |
| 294 | |
| 295 | /** |
| 296 | * Base class for implementing a callback for the result of {@link |
| 297 | * PrintDocumentAdapter#onLayout(PrintAttributes, PrintAttributes, |
Svetoslav | 6283608 | 2013-07-17 14:52:35 -0700 | [diff] [blame] | 298 | * CancellationSignal, LayoutResultCallback, Bundle)}. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 299 | */ |
| 300 | public static abstract class LayoutResultCallback { |
| 301 | |
| 302 | /** |
| 303 | * @hide |
| 304 | */ |
| 305 | public LayoutResultCallback() { |
| 306 | /* do nothing - hide constructor */ |
| 307 | } |
| 308 | |
| 309 | /** |
| 310 | * Notifies that the layout finished and whether the content changed. |
| 311 | * |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 312 | * @param info An info object describing the document. Cannot be <code>null</code>. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 313 | * @param changed Whether the layout changed. |
| 314 | * |
| 315 | * @see PrintDocumentInfo |
| 316 | */ |
| 317 | public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { |
| 318 | /* do nothing - stub */ |
| 319 | } |
| 320 | |
| 321 | /** |
| 322 | * Notifies that an error occurred while laying out the document. |
| 323 | * |
Svetoslav Ganov | 4d4c66d | 2013-10-24 18:04:39 -0700 | [diff] [blame] | 324 | * @param error The <strong>localized</strong> error message. |
| 325 | * shown to the user. May be <code>null</code> if error is unknown. |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 326 | */ |
| 327 | public void onLayoutFailed(CharSequence error) { |
| 328 | /* do nothing - stub */ |
| 329 | } |
Svetoslav Ganov | 85b1f88 | 2013-07-24 17:00:06 -0700 | [diff] [blame] | 330 | |
| 331 | /** |
| 332 | * Notifies that layout was cancelled as a result of a cancellation request. |
| 333 | */ |
| 334 | public void onLayoutCancelled() { |
| 335 | /* do nothing - stub */ |
| 336 | } |
Svetoslav Ganov | a002715 | 2013-06-25 14:59:53 -0700 | [diff] [blame] | 337 | } |
| 338 | } |