1 /* 2 * Copyright (C) 2010 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 dalvik.system; 18 19 import java.io.FileDescriptor; 20 import java.io.FileNotFoundException; 21 import java.io.FileOutputStream; 22 import java.io.IOException; 23 import java.math.BigInteger; 24 import java.net.SocketException; 25 26 /** 27 * Mechanism to let threads set restrictions on what code is allowed 28 * to do in their thread. 29 * 30 * <p>This is meant for applications to prevent certain blocking 31 * operations from running on their main event loop (or "UI") threads. 32 * 33 * <p>Note that this is all best-effort to catch most accidental mistakes 34 * and isn't intended to be a perfect mechanism, nor provide any sort of 35 * security. 36 * 37 * @hide 38 */ 39 public final class BlockGuard { 40 41 // TODO: refactor class name to something more generic, since its scope is 42 // growing beyond just blocking/logging. 43 44 public static final int DISALLOW_DISK_WRITE = 0x01; 45 public static final int DISALLOW_DISK_READ = 0x02; 46 public static final int DISALLOW_NETWORK = 0x04; 47 public static final int PASS_RESTRICTIONS_VIA_RPC = 0x08; 48 public static final int PENALTY_LOG = 0x10; 49 public static final int PENALTY_DIALOG = 0x20; 50 public static final int PENALTY_DEATH = 0x40; 51 52 public interface Policy { 53 /** 54 * Called on disk writes. 55 */ onWriteToDisk()56 void onWriteToDisk(); 57 58 /** 59 * Called on disk reads. 60 */ onReadFromDisk()61 void onReadFromDisk(); 62 63 /** 64 * Called on network operations. 65 */ onNetwork()66 void onNetwork(); 67 68 /** 69 * Called on unbuffered input/ouput operations. 70 */ onUnbufferedIO()71 void onUnbufferedIO(); 72 73 /** 74 * Returns the policy bitmask, for shipping over Binder calls 75 * to remote threads/processes and reinstantiating the policy 76 * there. The bits in the mask are from the DISALLOW_* and 77 * PENALTY_* constants. 78 */ getPolicyMask()79 int getPolicyMask(); 80 } 81 82 public static class BlockGuardPolicyException extends RuntimeException { 83 // bitmask of DISALLOW_*, PENALTY_*, etc flags 84 private final int mPolicyState; 85 private final int mPolicyViolated; 86 private final String mMessage; // may be null 87 BlockGuardPolicyException(int policyState, int policyViolated)88 public BlockGuardPolicyException(int policyState, int policyViolated) { 89 this(policyState, policyViolated, null); 90 } 91 BlockGuardPolicyException(int policyState, int policyViolated, String message)92 public BlockGuardPolicyException(int policyState, int policyViolated, String message) { 93 mPolicyState = policyState; 94 mPolicyViolated = policyViolated; 95 mMessage = message; 96 fillInStackTrace(); 97 } 98 getPolicy()99 public int getPolicy() { 100 return mPolicyState; 101 } 102 getPolicyViolation()103 public int getPolicyViolation() { 104 return mPolicyViolated; 105 } 106 getMessage()107 public String getMessage() { 108 // Note: do not change this format casually. It's 109 // somewhat unfortunately Parceled and passed around 110 // Binder calls and parsed back into an Exception by 111 // Android's StrictMode. This was the least invasive 112 // option and avoided a gross mix of Java Serialization 113 // combined with Parcels. 114 return "policy=" + mPolicyState + " violation=" + mPolicyViolated + 115 (mMessage == null ? "" : (" msg=" + mMessage)); 116 } 117 } 118 119 /** 120 * The default, permissive policy that doesn't prevent any operations. 121 */ 122 public static final Policy LAX_POLICY = new Policy() { 123 public void onWriteToDisk() {} 124 public void onReadFromDisk() {} 125 public void onNetwork() {} 126 public void onUnbufferedIO() {} 127 public int getPolicyMask() { 128 return 0; 129 } 130 }; 131 132 private static ThreadLocal<Policy> threadPolicy = new ThreadLocal<Policy>() { 133 @Override protected Policy initialValue() { 134 return LAX_POLICY; 135 } 136 }; 137 138 /** 139 * Get the current thread's policy. 140 * 141 * @return the current thread's policy. Never returns null. 142 * Will return the LAX_POLICY instance if nothing else is set. 143 */ getThreadPolicy()144 public static Policy getThreadPolicy() { 145 return threadPolicy.get(); 146 } 147 148 /** 149 * Sets the current thread's block guard policy. 150 * 151 * @param policy policy to set. May not be null. Use the public LAX_POLICY 152 * if you want to unset the active policy. 153 */ setThreadPolicy(Policy policy)154 public static void setThreadPolicy(Policy policy) { 155 if (policy == null) { 156 throw new NullPointerException("policy == null"); 157 } 158 threadPolicy.set(policy); 159 } 160 BlockGuard()161 private BlockGuard() {} 162 } 163