/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package dalvik.system; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import java.util.Objects; import libcore.util.NonNull; /** * Interface that enables {@code StrictMode} to install callbacks to implement * its policy detection and penalty behavior in {@code libcore} code. *

* The framework separately defines {@code StrictMode.ThreadPolicy} and * {@code StrictMode.VmPolicy}, so we mirror that separation here; the former is * designed for per-thread policies, and the latter for process-wide policies. *

* Note that this is all best-effort to catch most accidental mistakes and isn't * intended to be a perfect mechanism, nor provide any sort of security. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) @libcore.api.IntraCoreApi public final class BlockGuard { // TODO: refactor class name to something more generic, since its scope is // growing beyond just blocking/logging. /** * Per-thread interface used to implement {@code StrictMode.ThreadPolicy}. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) @libcore.api.IntraCoreApi public interface Policy { /** * Called on disk writes. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) void onWriteToDisk(); /** * Called on disk reads. * * @hide */ @UnsupportedAppUsage @SystemApi(client = MODULE_LIBRARIES) void onReadFromDisk(); /** * Called on network operations. * * @hide */ @UnsupportedAppUsage @libcore.api.IntraCoreApi void onNetwork(); /** * Called on unbuffered input/ouput operations. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) void onUnbufferedIO(); /** * Called on explicit GC request, i.e. Runtime.gc(). * * @hide */ void onExplicitGc(); /** * Returns the policy bitmask, for shipping over Binder calls * to remote threads/processes and reinstantiating the policy * there. The bits in the mask are from the {@code DISALLOW_*} and * {@code PENALTY_*} constants declared in {@code StrictMode} class. * * @return policy bitmask * * @hide */ @SystemApi(client = MODULE_LIBRARIES) int getPolicyMask(); } /** * Per-process interface used to implement {@code StrictMode.VmPolicy}. * @hide */ @SystemApi(client = MODULE_LIBRARIES) public interface VmPolicy { /** * Called by core libraries code when the given path is accessed. This * allows an implementation to alert developers to unexpected path * access, such as trying to access encrypted files before the * encryption key has been installed. *

* This only needs to be called once when a path is first accessed by * the process; it doesn't need to be invoked for each subsequent * read/write. (In contrast, we always need to call the per-thread * policy for every read/write, since ownership of an open file can move * between threads.) *

* Note that this is all best-effort to catch most accidental mistakes * and isn't intended to be a perfect mechanism, nor provide any sort of * security. * * @param path The path in the local file system that is being accessed * for reading or writing. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) void onPathAccess(@NonNull String path); } /** * @deprecated no longer actively used, but kept intact for hidden API lists. * * @hide */ @Deprecated public static class BlockGuardPolicyException extends RuntimeException { // bitmask of DISALLOW_*, PENALTY_*, etc flags @UnsupportedAppUsage private final int mPolicyState; @UnsupportedAppUsage private final int mPolicyViolated; @UnsupportedAppUsage private final String mMessage; // may be null public BlockGuardPolicyException(int policyState, int policyViolated) { this(policyState, policyViolated, null); } @UnsupportedAppUsage public BlockGuardPolicyException(int policyState, int policyViolated, String message) { mPolicyState = policyState; mPolicyViolated = policyViolated; mMessage = message; fillInStackTrace(); } public int getPolicy() { return mPolicyState; } public int getPolicyViolation() { return mPolicyViolated; } public String getMessage() { // Note: do not change this format casually. It's // somewhat unfortunately Parceled and passed around // Binder calls and parsed back into an Exception by // Android's StrictMode. This was the least invasive // option and avoided a gross mix of Java Serialization // combined with Parcels. return "policy=" + mPolicyState + " violation=" + mPolicyViolated + (mMessage == null ? "" : (" msg=" + mMessage)); } } /** * The default, permissive per-thread policy. * * @hide */ @UnsupportedAppUsage @SystemApi(client = MODULE_LIBRARIES) public static final Policy LAX_POLICY = new Policy() { @Override public String toString() { return "LAX_POLICY"; } @Override public void onWriteToDisk() {} @Override public void onReadFromDisk() {} @Override public void onNetwork() {} @Override public void onUnbufferedIO() {} @Override public void onExplicitGc() {} @Override public int getPolicyMask() { return 0; } }; /** * The default, permissive per-process policy. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) public static final VmPolicy LAX_VM_POLICY = new VmPolicy() { @Override public String toString() { return "LAX_VM_POLICY"; } @Override public void onPathAccess(String path) {} }; @UnsupportedAppUsage private static ThreadLocal threadPolicy = new ThreadLocal() { @Override protected Policy initialValue() { return LAX_POLICY; } }; private static volatile VmPolicy vmPolicy = LAX_VM_POLICY; /** * Get the per-thread policy for the current thread. * * @return the current thread's policy. Will return the {@link #LAX_POLICY} * instance if nothing else is set. * * @hide */ @UnsupportedAppUsage @SystemApi(client = MODULE_LIBRARIES) @libcore.api.IntraCoreApi public static @NonNull Policy getThreadPolicy() { return threadPolicy.get(); } /** * Sets the per-thread policy for the current thread. *

* This should only be called by {@code StrictMode}, since there can only be * one policy active at any given time. * * @param policy policy to set. Use the public {@link #LAX_POLICY} if you * want to unset the active policy. * * @hide */ @UnsupportedAppUsage @SystemApi(client = MODULE_LIBRARIES) public static void setThreadPolicy(@NonNull Policy policy) { threadPolicy.set(Objects.requireNonNull(policy)); } /** * Get the per-process policy for the current process. * * @return the current process's policy. Will return the * {@link #LAX_VM_POLICY} instance if nothing else is set. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) public static @NonNull VmPolicy getVmPolicy() { return vmPolicy; } /** * Set the per-process policy for the current process. *

* This should only be called by {@code StrictMode}, since there can only be * one policy active at any given time. * * @param policy policy to set. Use the public {@link #LAX_VM_POLICY} if you * want to unset the active policy. * * @hide */ @SystemApi(client = MODULE_LIBRARIES) public static void setVmPolicy(@NonNull VmPolicy policy) { vmPolicy = Objects.requireNonNull(policy); } private BlockGuard() {} }