1 // Copyright 2017 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; 6 7 import android.os.Build; 8 import android.os.StrictMode; 9 10 import java.io.Closeable; 11 12 /** 13 * Enables try-with-resources compatible StrictMode violation allowlisting. 14 * 15 * Prefer "ignored" as the variable name to appease Android Studio's "Unused symbol" inspection. 16 * 17 * Example: 18 * <pre> 19 * try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) { 20 * return Example.doThingThatRequiresDiskWrites(); 21 * } 22 * </pre> 23 * 24 */ 25 public final class StrictModeContext implements Closeable { 26 private final StrictMode.ThreadPolicy mThreadPolicy; 27 private final StrictMode.VmPolicy mVmPolicy; 28 StrictModeContext(StrictMode.ThreadPolicy threadPolicy, StrictMode.VmPolicy vmPolicy)29 private StrictModeContext(StrictMode.ThreadPolicy threadPolicy, StrictMode.VmPolicy vmPolicy) { 30 // TODO(crbug/1475610): Determine after auditing strict mode context usage if we should keep 31 // or remove these trace events. 32 TraceEvent.startAsync("StrictModeContext", hashCode()); 33 mThreadPolicy = threadPolicy; 34 mVmPolicy = vmPolicy; 35 } 36 StrictModeContext(StrictMode.ThreadPolicy threadPolicy)37 private StrictModeContext(StrictMode.ThreadPolicy threadPolicy) { 38 this(threadPolicy, null); 39 } 40 StrictModeContext(StrictMode.VmPolicy vmPolicy)41 private StrictModeContext(StrictMode.VmPolicy vmPolicy) { 42 this(null, vmPolicy); 43 } 44 45 /** 46 * Convenience method for disabling all VM-level StrictMode checks with try-with-resources. 47 * Includes everything listed here: 48 * https://developer.android.com/reference/android/os/StrictMode.VmPolicy.Builder.html 49 */ allowAllVmPolicies()50 public static StrictModeContext allowAllVmPolicies() { 51 try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowAllVmPolicies")) { 52 StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy(); 53 StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX); 54 return new StrictModeContext(oldPolicy); 55 } 56 } 57 58 /** 59 * Convenience method for disabling all thread-level StrictMode checks with try-with-resources. 60 * Includes everything listed here: 61 * https://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder.html 62 */ allowAllThreadPolicies()63 public static StrictModeContext allowAllThreadPolicies() { 64 try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowAllThreadPolicies")) { 65 StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); 66 StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX); 67 return new StrictModeContext(oldPolicy); 68 } 69 } 70 71 /** Convenience method for disabling StrictMode for disk-writes with try-with-resources. */ allowDiskWrites()72 public static StrictModeContext allowDiskWrites() { 73 try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowDiskWrites")) { 74 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); 75 return new StrictModeContext(oldPolicy); 76 } 77 } 78 79 /** Convenience method for disabling StrictMode for disk-reads with try-with-resources. */ allowDiskReads()80 public static StrictModeContext allowDiskReads() { 81 try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowDiskReads")) { 82 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); 83 return new StrictModeContext(oldPolicy); 84 } 85 } 86 87 /** Convenience method for disabling StrictMode for slow calls with try-with-resources. */ allowSlowCalls()88 public static StrictModeContext allowSlowCalls() { 89 try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowSlowCalls")) { 90 StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); 91 StrictMode.setThreadPolicy( 92 new StrictMode.ThreadPolicy.Builder(oldPolicy).permitCustomSlowCalls().build()); 93 return new StrictModeContext(oldPolicy); 94 } 95 } 96 97 /** 98 * Convenience method for disabling StrictMode for unbuffered input/output operations with 99 * try-with-resources. 100 * For API level 25- this method will do nothing; 101 * because StrictMode.ThreadPolicy.Builder#permitUnbufferedIo is added in API level 26. 102 */ allowUnbufferedIo()103 public static StrictModeContext allowUnbufferedIo() { 104 try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowUnbufferedIo")) { 105 StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); 106 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 107 StrictMode.setThreadPolicy( 108 new StrictMode.ThreadPolicy.Builder(oldPolicy) 109 .permitUnbufferedIo() 110 .build()); 111 } 112 return new StrictModeContext(oldPolicy); 113 } 114 } 115 116 @Override close()117 public void close() { 118 if (mThreadPolicy != null) { 119 StrictMode.setThreadPolicy(mThreadPolicy); 120 } 121 if (mVmPolicy != null) { 122 StrictMode.setVmPolicy(mVmPolicy); 123 } 124 TraceEvent.finishAsync("StrictModeContext", hashCode()); 125 } 126 } 127