Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 711ee498 authored by Wenhao Wang's avatar Wenhao Wang Committed by Android (Google) Code Review
Browse files

Merge "[Forensic] Add ForensicManager and permissions" into main

parents 9160d589 18b98714
Loading
Loading
Loading
Loading
+26 −0
Original line number Original line Diff line number Diff line
@@ -65,6 +65,7 @@ package android {
    field @FlaggedApi("android.crashrecovery.flags.enable_crashrecovery") public static final String BIND_EXPLICIT_HEALTH_CHECK_SERVICE = "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
    field @FlaggedApi("android.crashrecovery.flags.enable_crashrecovery") public static final String BIND_EXPLICIT_HEALTH_CHECK_SERVICE = "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
    field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE";
    field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE";
    field public static final String BIND_FIELD_CLASSIFICATION_SERVICE = "android.permission.BIND_FIELD_CLASSIFICATION_SERVICE";
    field public static final String BIND_FIELD_CLASSIFICATION_SERVICE = "android.permission.BIND_FIELD_CLASSIFICATION_SERVICE";
    field @FlaggedApi("android.security.afl_api") public static final String BIND_FORENSIC_EVENT_TRANSPORT_SERVICE = "android.permission.BIND_FORENSIC_EVENT_TRANSPORT_SERVICE";
    field public static final String BIND_GBA_SERVICE = "android.permission.BIND_GBA_SERVICE";
    field public static final String BIND_GBA_SERVICE = "android.permission.BIND_GBA_SERVICE";
    field public static final String BIND_HOTWORD_DETECTION_SERVICE = "android.permission.BIND_HOTWORD_DETECTION_SERVICE";
    field public static final String BIND_HOTWORD_DETECTION_SERVICE = "android.permission.BIND_HOTWORD_DETECTION_SERVICE";
    field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
    field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
@@ -209,6 +210,7 @@ package android {
    field @FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled") public static final String MANAGE_ENHANCED_CONFIRMATION_STATES = "android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES";
    field @FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled") public static final String MANAGE_ENHANCED_CONFIRMATION_STATES = "android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES";
    field public static final String MANAGE_ETHERNET_NETWORKS = "android.permission.MANAGE_ETHERNET_NETWORKS";
    field public static final String MANAGE_ETHERNET_NETWORKS = "android.permission.MANAGE_ETHERNET_NETWORKS";
    field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
    field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
    field @FlaggedApi("android.security.afl_api") public static final String MANAGE_FORENSIC_STATE = "android.permission.MANAGE_FORENSIC_STATE";
    field public static final String MANAGE_GAME_ACTIVITY = "android.permission.MANAGE_GAME_ACTIVITY";
    field public static final String MANAGE_GAME_ACTIVITY = "android.permission.MANAGE_GAME_ACTIVITY";
    field public static final String MANAGE_GAME_MODE = "android.permission.MANAGE_GAME_MODE";
    field public static final String MANAGE_GAME_MODE = "android.permission.MANAGE_GAME_MODE";
    field @FlaggedApi("android.media.tv.flags.media_quality_fw") public static final String MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE = "android.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE";
    field @FlaggedApi("android.media.tv.flags.media_quality_fw") public static final String MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE = "android.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE";
@@ -304,6 +306,7 @@ package android {
    field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
    field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
    field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
    field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
    field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
    field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
    field @FlaggedApi("android.security.afl_api") public static final String READ_FORENSIC_STATE = "android.permission.READ_FORENSIC_STATE";
    field public static final String READ_GLOBAL_APP_SEARCH_DATA = "android.permission.READ_GLOBAL_APP_SEARCH_DATA";
    field public static final String READ_GLOBAL_APP_SEARCH_DATA = "android.permission.READ_GLOBAL_APP_SEARCH_DATA";
    field @FlaggedApi("android.content.pm.get_resolved_apk_path") public static final String READ_INSTALLED_SESSION_PATHS = "android.permission.READ_INSTALLED_SESSION_PATHS";
    field @FlaggedApi("android.content.pm.get_resolved_apk_path") public static final String READ_INSTALLED_SESSION_PATHS = "android.permission.READ_INSTALLED_SESSION_PATHS";
    field public static final String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
    field public static final String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
@@ -12594,6 +12597,29 @@ package android.security.advancedprotection {
}
}
package android.security.forensic {
  @FlaggedApi("android.security.afl_api") public class ForensicManager {
    method @RequiresPermission(android.Manifest.permission.READ_FORENSIC_STATE) public void addStateCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
    method @RequiresPermission(android.Manifest.permission.MANAGE_FORENSIC_STATE) public void disable(@NonNull java.util.concurrent.Executor, @NonNull android.security.forensic.ForensicManager.CommandCallback);
    method @RequiresPermission(android.Manifest.permission.MANAGE_FORENSIC_STATE) public void enable(@NonNull java.util.concurrent.Executor, @NonNull android.security.forensic.ForensicManager.CommandCallback);
    method @RequiresPermission(android.Manifest.permission.READ_FORENSIC_STATE) public void removeStateCallback(@NonNull java.util.function.Consumer<java.lang.Integer>);
    field public static final int ERROR_DATA_SOURCE_UNAVAILABLE = 4; // 0x4
    field public static final int ERROR_PERMISSION_DENIED = 1; // 0x1
    field public static final int ERROR_TRANSPORT_UNAVAILABLE = 3; // 0x3
    field public static final int ERROR_UNKNOWN = 0; // 0x0
    field public static final int STATE_DISABLED = 1; // 0x1
    field public static final int STATE_ENABLED = 2; // 0x2
    field public static final int STATE_UNKNOWN = 0; // 0x0
  }
  public static interface ForensicManager.CommandCallback {
    method public void onFailure(int);
    method public void onSuccess();
  }
}
package android.security.keystore {
package android.security.keystore {
  public class AndroidKeyStoreProvider extends java.security.Provider {
  public class AndroidKeyStoreProvider extends java.security.Provider {
+14 −0
Original line number Original line Diff line number Diff line
@@ -239,6 +239,8 @@ import android.security.advancedprotection.AdvancedProtectionManager;
import android.security.advancedprotection.IAdvancedProtectionService;
import android.security.advancedprotection.IAdvancedProtectionService;
import android.security.attestationverification.AttestationVerificationManager;
import android.security.attestationverification.AttestationVerificationManager;
import android.security.attestationverification.IAttestationVerificationManagerService;
import android.security.attestationverification.IAttestationVerificationManagerService;
import android.security.forensic.ForensicManager;
import android.security.forensic.IForensicService;
import android.security.keystore.KeyStoreManager;
import android.security.keystore.KeyStoreManager;
import android.service.oemlock.IOemLockService;
import android.service.oemlock.IOemLockService;
import android.service.oemlock.OemLockManager;
import android.service.oemlock.OemLockManager;
@@ -1793,6 +1795,18 @@ public final class SystemServiceRegistry {
                    }
                    }
                });
                });


        registerService(Context.FORENSIC_SERVICE, ForensicManager.class,
                new CachedServiceFetcher<ForensicManager>() {
                    @Override
                    public ForensicManager createService(ContextImpl ctx)
                            throws ServiceNotFoundException {
                        IBinder b = ServiceManager.getServiceOrThrow(
                                Context.FORENSIC_SERVICE);
                        IForensicService service = IForensicService.Stub.asInterface(b);
                        return new ForensicManager(service);
                    }
                });

        sInitializing = true;
        sInitializing = true;
        try {
        try {
            // Note: the following functions need to be @SystemApis, once they become mainline
            // Note: the following functions need to be @SystemApis, once they become mainline
+276 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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 android.security.forensic;

import static android.Manifest.permission.MANAGE_FORENSIC_STATE;
import static android.Manifest.permission.READ_FORENSIC_STATE;

import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.security.Flags;
import android.util.Log;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * ForensicManager manages the forensic logging on Android devices.
 * Upon user consent, forensic logging collects various device events for
 * off-device investigation of potential device compromise.
 * <p>
 * Forensic logging can either be enabled ({@link #STATE_ENABLED}
 * or disabled ({@link #STATE_DISABLED}).
 * <p>
 * The Forensic logs will be transferred to
 * {@link android.security.forensic.ForensicEventTransport}.
 *
 * @hide
 */
@SystemApi
@FlaggedApi(Flags.FLAG_AFL_API)
@SystemService(Context.FORENSIC_SERVICE)
public class ForensicManager {
    private static final String TAG = "ForensicManager";

    /** @hide */
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "STATE_" }, value = {
            STATE_UNKNOWN,
            STATE_DISABLED,
            STATE_ENABLED
    })
    public @interface ForensicState {}

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "ERROR_" }, value = {
            ERROR_UNKNOWN,
            ERROR_PERMISSION_DENIED,
            ERROR_TRANSPORT_UNAVAILABLE,
            ERROR_DATA_SOURCE_UNAVAILABLE
    })
    public @interface ForensicError {}

    /**
     * Indicates an unknown state
     */
    public static final int STATE_UNKNOWN = IForensicServiceStateCallback.State.UNKNOWN;

    /**
     * Indicates an state that the forensic is turned off.
     */
    public static final int STATE_DISABLED = IForensicServiceStateCallback.State.DISABLED;

    /**
     * Indicates an state that the forensic is turned on.
     */
    public static final int STATE_ENABLED = IForensicServiceStateCallback.State.ENABLED;

    /**
     * Indicates an unknown error
     */
    public static final int ERROR_UNKNOWN = IForensicServiceCommandCallback.ErrorCode.UNKNOWN;

    /**
     * Indicates an error due to insufficient access rights.
     */
    public static final int ERROR_PERMISSION_DENIED =
            IForensicServiceCommandCallback.ErrorCode.PERMISSION_DENIED;

    /**
     * Indicates an error due to unavailability of the forensic event transport.
     */
    public static final int ERROR_TRANSPORT_UNAVAILABLE =
            IForensicServiceCommandCallback.ErrorCode.TRANSPORT_UNAVAILABLE;

    /**
     * Indicates an error due to unavailability of the data source.
     */
    public static final int ERROR_DATA_SOURCE_UNAVAILABLE =
            IForensicServiceCommandCallback.ErrorCode.DATA_SOURCE_UNAVAILABLE;


    private final IForensicService mService;

    private final ConcurrentHashMap<Consumer<Integer>, IForensicServiceStateCallback>
            mStateCallbacks = new ConcurrentHashMap<>();

    /**
     * Constructor
     *
     * @param service A valid instance of IForensicService.
     * @hide
     */
    public ForensicManager(IForensicService service) {
        mService = service;
    }

    /**
     * Add a callback to monitor the state of the ForensicService.
     *
     * @param executor The executor through which the callback should be invoked.
     * @param callback The callback for state change.
     *                 Once the callback is registered, the callback will be called
     *                 to reflect the init state.
     *                 The callback can be registered only once.
     */
    @RequiresPermission(READ_FORENSIC_STATE)
    public void addStateCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull @ForensicState Consumer<Integer> callback) {
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);

        if (mStateCallbacks.get(callback) != null) {
            Log.d(TAG, "addStateCallback callback already present");
            return;
        }

        final IForensicServiceStateCallback wrappedCallback =
                new IForensicServiceStateCallback.Stub() {
                    @Override
                    public void onStateChange(int state) {
                        executor.execute(() -> callback.accept(state));
                    }
                };
        try {
            mService.addStateCallback(wrappedCallback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        mStateCallbacks.put(callback, wrappedCallback);
    }

    /**
     * Remove a callback to monitor the state of the ForensicService.
     *
     * @param callback The callback to remove.
     */
    @RequiresPermission(READ_FORENSIC_STATE)
    public void removeStateCallback(@NonNull Consumer<@ForensicState Integer> callback) {
        Objects.requireNonNull(callback);
        if (!mStateCallbacks.containsKey(callback)) {
            Log.d(TAG, "removeStateCallback callback not present");
            return;
        }

        IForensicServiceStateCallback wrappedCallback = mStateCallbacks.get(callback);

        try {
            mService.removeStateCallback(wrappedCallback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        mStateCallbacks.remove(callback);
    }

    /**
     * Enable forensic logging.
     * If successful, ForensicService will transition to {@link #STATE_ENABLED} state.
     * <p>
     * When forensic logging is enabled, various device events will be collected and
     * sent over to the registered {@link android.security.forensic.ForensicEventTransport}.
     *
     * @param executor The executor through which the callback should be invoked.
     * @param callback The callback for the command result.
     */
    @RequiresPermission(MANAGE_FORENSIC_STATE)
    public void enable(@NonNull @CallbackExecutor Executor executor,
            @NonNull CommandCallback callback) {
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);
        try {
            mService.enable(new IForensicServiceCommandCallback.Stub() {
                @Override
                public void onSuccess() {
                    executor.execute(callback::onSuccess);
                }

                @Override
                public void onFailure(int error) {
                    executor.execute(() -> callback.onFailure(error));
                }
            });
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Disable forensic logging.
     * If successful, ForensicService will transition to {@link #STATE_DISABLED}.
     * <p>
     * When forensic logging is disabled, device events will no longer be collected.
     * Any events that have been collected but not yet sent to ForensicEventTransport
     * will be transferred as a final batch.
     *
     * @param executor The executor through which the callback should be invoked.
     * @param callback The callback for the command result.
     */
    @RequiresPermission(MANAGE_FORENSIC_STATE)
    public void disable(@NonNull @CallbackExecutor Executor executor,
            @NonNull CommandCallback callback) {
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);
        try {
            mService.disable(new IForensicServiceCommandCallback.Stub() {
                @Override
                public void onSuccess() {
                    executor.execute(callback::onSuccess);
                }

                @Override
                public void onFailure(int error) {
                    executor.execute(() -> callback.onFailure(error));
                }
            });
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Callback used in {@link #enable} and {@link #disable} to indicate the result of the command.
     */
    public interface CommandCallback {
        /**
         * Called when command succeeds.
         */
        void onSuccess();

        /**
         * Called when command fails.
         * @param error The error number.
         */
        void onFailure(@ForensicError int error);
    }
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -20,7 +20,7 @@ import android.security.forensic.ForensicEvent;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.AndroidFuture;


/** {@hide} */
/** {@hide} */
oneway interface IBackupTransport {
oneway interface IForensicEventTransport {
    /**
    /**
     * Initialize the server side.
     * Initialize the server side.
     */
     */
+6 −3
Original line number Original line Diff line number Diff line
@@ -24,9 +24,12 @@ import android.security.forensic.IForensicServiceStateCallback;
 * @hide
 * @hide
 */
 */
interface IForensicService {
interface IForensicService {
    void monitorState(IForensicServiceStateCallback callback);
    @EnforcePermission("READ_FORENSIC_STATE")
    void makeVisible(IForensicServiceCommandCallback callback);
    void addStateCallback(IForensicServiceStateCallback callback);
    void makeInvisible(IForensicServiceCommandCallback callback);
    @EnforcePermission("READ_FORENSIC_STATE")
    void removeStateCallback(IForensicServiceStateCallback callback);
    @EnforcePermission("MANAGE_FORENSIC_STATE")
    void enable(IForensicServiceCommandCallback callback);
    void enable(IForensicServiceCommandCallback callback);
    @EnforcePermission("MANAGE_FORENSIC_STATE")
    void disable(IForensicServiceCommandCallback callback);
    void disable(IForensicServiceCommandCallback callback);
}
}
Loading