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