• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.base.test.util;
6 
7 import androidx.test.InstrumentationRegistry;
8 
9 import org.chromium.base.StrictModeContext;
10 
11 import java.io.Closeable;
12 import java.io.IOException;
13 import java.util.concurrent.Callable;
14 
15 /**
16  * A Closeable that manages another Closeable running on android's main thread.
17  *
18  * The Closeable is both created and closed on the main thread.
19  * Note that both operations are synchronous.
20  */
21 public final class CloseableOnMainThread implements Closeable {
22     private Closeable mCloseable;
23     private Exception mException;
24 
25     /**
26      * Execute a closeable callable on the main thread, blocking until it is complete.
27      *
28      * @param initializer A closeable callable to be executed on the main thread
29      * @throws Exception Thrown if the initializer throws Exception
30      */
CloseableOnMainThread(Callable<Closeable> initializer)31     public CloseableOnMainThread(Callable<Closeable> initializer) throws Exception {
32         InstrumentationRegistry.getInstrumentation()
33                 .runOnMainSync(
34                         () -> {
35                             try {
36                                 mCloseable = initializer.call();
37                             } catch (Exception e) {
38                                 mException = e;
39                             }
40                         });
41         if (mException != null) {
42             throw new Exception(mException.getCause());
43         }
44     }
45 
46     /**
47      * Close the closeable on the main thread, blocking until it is complete.
48      *
49      * @throws IOException Thrown if the closeable throws IOException
50      */
51     @Override
close()52     public void close() throws IOException {
53         InstrumentationRegistry.getInstrumentation()
54                 .runOnMainSync(
55                         () -> {
56                             try {
57                                 mCloseable.close();
58                             } catch (IOException e) {
59                                 mException = e;
60                             }
61                         });
62         if (mException != null) {
63             throw new IOException(mException.getCause());
64         }
65     }
66 
67     /**
68      * Enables try-with-resources compatible StrictMode violation allowlisting on android's main
69      * thread.
70      *
71      * Prefer "ignored" as the variable name to appease Android Studio's "Unused symbol" inspection.
72      *
73      * Example:
74      * <pre>
75      *     try (CloseableOnMainThread ignored =
76      *                     CloseableOnMainThread.StrictMode.allowDiskWrites()) {
77      *         return Example.doThingThatRequiresDiskWrites();
78      *     }
79      * </pre>
80      *
81      */
82     public static class StrictMode {
StrictMode()83         private StrictMode() {}
84 
85         /**
86          * Convenience method for disabling all thread-level StrictMode checks with
87          * try-with-resources. Includes everything listed here:
88          *     https://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder.html
89          */
allowAllThreadPolicies()90         public static CloseableOnMainThread allowAllThreadPolicies() throws Exception {
91             return new CloseableOnMainThread(
92                     () -> {
93                         return StrictModeContext.allowAllThreadPolicies();
94                     });
95         }
96 
97         /** Convenience method for disabling StrictMode for disk-writes with try-with-resources. */
allowDiskWrites()98         public static CloseableOnMainThread allowDiskWrites() throws Exception {
99             return new CloseableOnMainThread(
100                     () -> {
101                         return StrictModeContext.allowDiskWrites();
102                     });
103         }
104     }
105 }
106