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 * Returns the policy bitmask, for shipping over Binder calls 70 * to remote threads/processes and reinstantiating the policy 71 * there. The bits in the mask are from the DISALLOW_* and 72 * PENALTY_* constants. 73 */ getPolicyMask()74 int getPolicyMask(); 75 } 76 77 public static class BlockGuardPolicyException extends RuntimeException { 78 // bitmask of DISALLOW_*, PENALTY_*, etc flags 79 private final int mPolicyState; 80 private final int mPolicyViolated; 81 private final String mMessage; // may be null 82 BlockGuardPolicyException(int policyState, int policyViolated)83 public BlockGuardPolicyException(int policyState, int policyViolated) { 84 this(policyState, policyViolated, null); 85 } 86 BlockGuardPolicyException(int policyState, int policyViolated, String message)87 public BlockGuardPolicyException(int policyState, int policyViolated, String message) { 88 mPolicyState = policyState; 89 mPolicyViolated = policyViolated; 90 mMessage = message; 91 fillInStackTrace(); 92 } 93 getPolicy()94 public int getPolicy() { 95 return mPolicyState; 96 } 97 getPolicyViolation()98 public int getPolicyViolation() { 99 return mPolicyViolated; 100 } 101 getMessage()102 public String getMessage() { 103 // Note: do not change this format casually. It's 104 // somewhat unfortunately Parceled and passed around 105 // Binder calls and parsed back into an Exception by 106 // Android's StrictMode. This was the least invasive 107 // option and avoided a gross mix of Java Serialization 108 // combined with Parcels. 109 return "policy=" + mPolicyState + " violation=" + mPolicyViolated + 110 (mMessage == null ? "" : (" msg=" + mMessage)); 111 } 112 } 113 114 /** 115 * The default, permissive policy that doesn't prevent any operations. 116 */ 117 public static final Policy LAX_POLICY = new Policy() { 118 public void onWriteToDisk() {} 119 public void onReadFromDisk() {} 120 public void onNetwork() {} 121 public int getPolicyMask() { 122 return 0; 123 } 124 }; 125 126 private static ThreadLocal<Policy> threadPolicy = new ThreadLocal<Policy>() { 127 @Override protected Policy initialValue() { 128 return LAX_POLICY; 129 } 130 }; 131 132 /** 133 * Get the current thread's policy. 134 * 135 * @return the current thread's policy. Never returns null. 136 * Will return the LAX_POLICY instance if nothing else is set. 137 */ getThreadPolicy()138 public static Policy getThreadPolicy() { 139 return threadPolicy.get(); 140 } 141 142 /** 143 * Sets the current thread's block guard policy. 144 * 145 * @param policy policy to set. May not be null. Use the public LAX_POLICY 146 * if you want to unset the active policy. 147 */ setThreadPolicy(Policy policy)148 public static void setThreadPolicy(Policy policy) { 149 if (policy == null) { 150 throw new NullPointerException("policy == null"); 151 } 152 threadPolicy.set(policy); 153 } 154 BlockGuard()155 private BlockGuard() {} 156 } 157