292 lines
9.1 KiB
Java
292 lines
9.1 KiB
Java
![]() |
/*
|
||
|
* 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.
|
||
|
* <p>
|
||
|
* 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.
|
||
|
* <p>
|
||
|
* 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.
|
||
|
* <p>
|
||
|
* 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.)
|
||
|
* <p>
|
||
|
* 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<Policy> threadPolicy = new ThreadLocal<Policy>() {
|
||
|
@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.
|
||
|
* <p>
|
||
|
* 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.
|
||
|
* <p>
|
||
|
* 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() {}
|
||
|
}
|