Home | History | Annotate | Download | only in system
      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          */
     56         void onWriteToDisk();
     57 
     58         /**
     59          * Called on disk reads.
     60          */
     61         void onReadFromDisk();
     62 
     63         /**
     64          * Called on network operations.
     65          */
     66         void onNetwork();
     67 
     68         /**
     69          * Called on unbuffered input/ouput operations.
     70          */
     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          */
     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 
     88         public BlockGuardPolicyException(int policyState, int policyViolated) {
     89             this(policyState, policyViolated, null);
     90         }
     91 
     92         public BlockGuardPolicyException(int policyState, int policyViolated, String message) {
     93             mPolicyState = policyState;
     94             mPolicyViolated = policyViolated;
     95             mMessage = message;
     96             fillInStackTrace();
     97         }
     98 
     99         public int getPolicy() {
    100             return mPolicyState;
    101         }
    102 
    103         public int getPolicyViolation() {
    104             return mPolicyViolated;
    105         }
    106 
    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      */
    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      */
    154     public static void setThreadPolicy(Policy policy) {
    155         if (policy == null) {
    156             throw new NullPointerException("policy == null");
    157         }
    158         threadPolicy.set(policy);
    159     }
    160 
    161     private BlockGuard() {}
    162 }
    163