/*
 * Copyright (C) 2023 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 com.android.server.healthconnect;

import static android.Manifest.permission.MIGRATE_HEALTH_CONNECT_DATA;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.health.connect.Constants.DEFAULT_LONG;
import static android.health.connect.Constants.READ;
import static android.health.connect.HealthConnectException.ERROR_INTERNAL;
import static android.health.connect.HealthConnectException.ERROR_SECURITY;
import static android.health.connect.HealthPermissions.MANAGE_HEALTH_DATA_PERMISSION;

import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.DELETE_DATA;
import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.GET_CHANGES;
import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.GET_CHANGES_TOKEN;
import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.INSERT_DATA;
import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.READ_AGGREGATED_DATA;
import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.READ_DATA;
import static com.android.server.healthconnect.logging.HealthConnectServiceLogger.ApiMethods.UPDATE_DATA;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.AttributionSource;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.sqlite.SQLiteException;
import android.health.connect.Constants;
import android.health.connect.FetchDataOriginsPriorityOrderResponse;
import android.health.connect.HealthConnectDataState;
import android.health.connect.HealthConnectException;
import android.health.connect.HealthConnectManager;
import android.health.connect.HealthConnectManager.DataDownloadState;
import android.health.connect.HealthDataCategory;
import android.health.connect.HealthPermissions;
import android.health.connect.RecordTypeInfoResponse;
import android.health.connect.accesslog.AccessLog;
import android.health.connect.accesslog.AccessLogsResponseParcel;
import android.health.connect.aidl.ActivityDatesRequestParcel;
import android.health.connect.aidl.ActivityDatesResponseParcel;
import android.health.connect.aidl.AggregateDataRequestParcel;
import android.health.connect.aidl.ApplicationInfoResponseParcel;
import android.health.connect.aidl.DeleteUsingFiltersRequestParcel;
import android.health.connect.aidl.GetPriorityResponseParcel;
import android.health.connect.aidl.HealthConnectExceptionParcel;
import android.health.connect.aidl.IAccessLogsResponseCallback;
import android.health.connect.aidl.IActivityDatesResponseCallback;
import android.health.connect.aidl.IAggregateRecordsResponseCallback;
import android.health.connect.aidl.IApplicationInfoResponseCallback;
import android.health.connect.aidl.IChangeLogsResponseCallback;
import android.health.connect.aidl.IDataStagingFinishedCallback;
import android.health.connect.aidl.IEmptyResponseCallback;
import android.health.connect.aidl.IGetChangeLogTokenCallback;
import android.health.connect.aidl.IGetHealthConnectDataStateCallback;
import android.health.connect.aidl.IGetHealthConnectMigrationUiStateCallback;
import android.health.connect.aidl.IGetPriorityResponseCallback;
import android.health.connect.aidl.IHealthConnectService;
import android.health.connect.aidl.IInsertRecordsResponseCallback;
import android.health.connect.aidl.IMigrationCallback;
import android.health.connect.aidl.IReadRecordsResponseCallback;
import android.health.connect.aidl.IRecordTypeInfoResponseCallback;
import android.health.connect.aidl.InsertRecordsResponseParcel;
import android.health.connect.aidl.ReadRecordsRequestParcel;
import android.health.connect.aidl.ReadRecordsResponseParcel;
import android.health.connect.aidl.RecordIdFiltersParcel;
import android.health.connect.aidl.RecordTypeInfoResponseParcel;
import android.health.connect.aidl.RecordsParcel;
import android.health.connect.aidl.UpdatePriorityRequestParcel;
import android.health.connect.changelog.ChangeLogTokenRequest;
import android.health.connect.changelog.ChangeLogTokenResponse;
import android.health.connect.changelog.ChangeLogsRequest;
import android.health.connect.changelog.ChangeLogsResponse;
import android.health.connect.changelog.ChangeLogsResponse.DeletedLog;
import android.health.connect.datatypes.AppInfo;
import android.health.connect.datatypes.DataOrigin;
import android.health.connect.datatypes.Record;
import android.health.connect.internal.datatypes.RecordInternal;
import android.health.connect.internal.datatypes.utils.AggregationTypeIdMapper;
import android.health.connect.internal.datatypes.utils.RecordMapper;
import android.health.connect.internal.datatypes.utils.RecordTypePermissionCategoryMapper;
import android.health.connect.migration.HealthConnectMigrationUiState;
import android.health.connect.migration.MigrationEntityParcel;
import android.health.connect.migration.MigrationException;
import android.health.connect.ratelimiter.RateLimiter;
import android.health.connect.ratelimiter.RateLimiter.QuotaCategory;
import android.health.connect.ratelimiter.RateLimiterException;
import android.health.connect.restore.BackupFileNamesSet;
import android.health.connect.restore.StageRemoteDataException;
import android.health.connect.restore.StageRemoteDataRequest;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.permission.PermissionManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalManagerRegistry;
import com.android.server.appop.AppOpsManagerLocal;
import com.android.server.healthconnect.backuprestore.BackupRestore;
import com.android.server.healthconnect.logging.HealthConnectServiceLogger;
import com.android.server.healthconnect.migration.DataMigrationManager;
import com.android.server.healthconnect.migration.MigrationCleaner;
import com.android.server.healthconnect.migration.MigrationStateManager;
import com.android.server.healthconnect.migration.MigrationUiStateManager;
import com.android.server.healthconnect.migration.PriorityMigrationHelper;
import com.android.server.healthconnect.permission.DataPermissionEnforcer;
import com.android.server.healthconnect.permission.FirstGrantTimeManager;
import com.android.server.healthconnect.permission.HealthConnectPermissionHelper;
import com.android.server.healthconnect.storage.AutoDeleteService;
import com.android.server.healthconnect.storage.TransactionManager;
import com.android.server.healthconnect.storage.datatypehelpers.AccessLogsHelper;
import com.android.server.healthconnect.storage.datatypehelpers.ActivityDateHelper;
import com.android.server.healthconnect.storage.datatypehelpers.AppInfoHelper;
import com.android.server.healthconnect.storage.datatypehelpers.ChangeLogsHelper;
import com.android.server.healthconnect.storage.datatypehelpers.ChangeLogsRequestHelper;
import com.android.server.healthconnect.storage.datatypehelpers.DeviceInfoHelper;
import com.android.server.healthconnect.storage.datatypehelpers.HealthDataCategoryPriorityHelper;
import com.android.server.healthconnect.storage.datatypehelpers.MigrationEntityHelper;
import com.android.server.healthconnect.storage.datatypehelpers.RecordHelper;
import com.android.server.healthconnect.storage.request.AggregateTransactionRequest;
import com.android.server.healthconnect.storage.request.DeleteTransactionRequest;
import com.android.server.healthconnect.storage.request.ReadTransactionRequest;
import com.android.server.healthconnect.storage.request.UpsertTransactionRequest;
import com.android.server.healthconnect.storage.utils.RecordHelperProvider;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * IHealthConnectService's implementation
 *
 * @hide
 */
final class HealthConnectServiceImpl extends IHealthConnectService.Stub {
    private static final String TAG = "HealthConnectService";
    // Permission for test api for deleting staged data
    private static final String DELETE_STAGED_HEALTH_CONNECT_REMOTE_DATA_PERMISSION =
            "android.permission.DELETE_STAGED_HEALTH_CONNECT_REMOTE_DATA";
    // Allows an application to act as a backup inter-agent to send and receive HealthConnect data
    private static final String HEALTH_CONNECT_BACKUP_INTER_AGENT_PERMISSION =
            "android.permission.HEALTH_CONNECT_BACKUP_INTER_AGENT";

    private static final String TAG_INSERT = "HealthConnectInsert";
    private static final String TAG_READ = "HealthConnectRead";
    private static final String TAG_GRANT_PERMISSION = "HealthConnectGrantReadPermissions";
    private static final String TAG_READ_PERMISSION = "HealthConnectReadPermission";
    private static final String TAG_INSERT_SUBTASKS = "HealthConnectInsertSubtasks";

    private static final String TAG_DELETE_SUBTASKS = "HealthConnectDeleteSubtasks";
    private static final String TAG_READ_SUBTASKS = "HealthConnectReadSubtasks";
    private static final int TRACE_TAG_INSERT = TAG_INSERT.hashCode();
    private static final int TRACE_TAG_READ = TAG_READ.hashCode();
    private static final int TRACE_TAG_GRANT_PERMISSION = TAG_GRANT_PERMISSION.hashCode();
    private static final int TRACE_TAG_READ_PERMISSION = TAG_READ_PERMISSION.hashCode();
    private static final int TRACE_TAG_INSERT_SUBTASKS = TAG_INSERT_SUBTASKS.hashCode();
    private static final int TRACE_TAG_DELETE_SUBTASKS = TAG_DELETE_SUBTASKS.hashCode();
    private static final int TRACE_TAG_READ_SUBTASKS = TAG_READ_SUBTASKS.hashCode();

    private final TransactionManager mTransactionManager;
    private final HealthConnectPermissionHelper mPermissionHelper;
    private final FirstGrantTimeManager mFirstGrantTimeManager;
    private final Context mContext;
    private final PermissionManager mPermissionManager;

    private final BackupRestore mBackupRestore;
    private final MigrationStateManager mMigrationStateManager;

    private final DataPermissionEnforcer mDataPermissionEnforcer;

    private final AppOpsManagerLocal mAppOpsManagerLocal;
    private final MigrationUiStateManager mMigrationUiStateManager;

    private volatile UserHandle mCurrentForegroundUser;

    HealthConnectServiceImpl(
            TransactionManager transactionManager,
            HealthConnectPermissionHelper permissionHelper,
            MigrationCleaner migrationCleaner,
            FirstGrantTimeManager firstGrantTimeManager,
            MigrationStateManager migrationStateManager,
            MigrationUiStateManager migrationUiStateManager,
            Context context) {
        mTransactionManager = transactionManager;
        mPermissionHelper = permissionHelper;
        mFirstGrantTimeManager = firstGrantTimeManager;
        mContext = context;
        mCurrentForegroundUser = context.getUser();
        mPermissionManager = mContext.getSystemService(PermissionManager.class);
        mMigrationStateManager = migrationStateManager;
        mDataPermissionEnforcer = new DataPermissionEnforcer(mPermissionManager, mContext);
        mAppOpsManagerLocal = LocalManagerRegistry.getManager(AppOpsManagerLocal.class);
        mBackupRestore =
                new BackupRestore(mFirstGrantTimeManager, mMigrationStateManager, mContext);
        mMigrationUiStateManager = migrationUiStateManager;
        migrationCleaner.attachTo(migrationStateManager);
        mMigrationUiStateManager.attachTo(migrationStateManager);
    }

    public void onUserSwitching(UserHandle currentForegroundUser) {
        mCurrentForegroundUser = currentForegroundUser;
        mBackupRestore.setupForUser(currentForegroundUser);
    }

    @Override
    public void grantHealthPermission(
            @NonNull String packageName, @NonNull String permissionName, @NonNull UserHandle user) {
        throwIllegalStateExceptionIfDataSyncInProgress();
        Trace.traceBegin(TRACE_TAG_GRANT_PERMISSION, TAG_GRANT_PERMISSION);
        mPermissionHelper.grantHealthPermission(packageName, permissionName, user);
        Trace.traceEnd(TRACE_TAG_GRANT_PERMISSION);
    }

    @Override
    public void revokeHealthPermission(
            @NonNull String packageName,
            @NonNull String permissionName,
            @Nullable String reason,
            @NonNull UserHandle user) {
        throwIllegalStateExceptionIfDataSyncInProgress();
        mPermissionHelper.revokeHealthPermission(packageName, permissionName, reason, user);
    }

    @Override
    public void revokeAllHealthPermissions(
            @NonNull String packageName, @Nullable String reason, @NonNull UserHandle user) {
        throwIllegalStateExceptionIfDataSyncInProgress();
        mPermissionHelper.revokeAllHealthPermissions(packageName, reason, user);
    }

    @Override
    public List<String> getGrantedHealthPermissions(
            @NonNull String packageName, @NonNull UserHandle user) {
        throwIllegalStateExceptionIfDataSyncInProgress();
        Trace.traceBegin(TRACE_TAG_READ_PERMISSION, TAG_READ_PERMISSION);
        List<String> grantedPermissions =
                mPermissionHelper.getGrantedHealthPermissions(packageName, user);
        Trace.traceEnd(TRACE_TAG_READ_PERMISSION);
        return grantedPermissions;
    }

    @Override
    public long getHistoricalAccessStartDateInMilliseconds(
            @NonNull String packageName, @NonNull UserHandle userHandle) {
        throwIllegalStateExceptionIfDataSyncInProgress();
        Instant date = mPermissionHelper.getHealthDataStartDateAccess(packageName, userHandle);
        if (date == null) {
            return Constants.DEFAULT_LONG;
        } else {
            return date.toEpochMilli();
        }
    }

    /**
     * Inserts {@code recordsParcel} into the HealthConnect database.
     *
     * @param recordsParcel parcel for list of records to be inserted.
     * @param callback Callback to receive result of performing this operation. The keys returned in
     *     {@link InsertRecordsResponseParcel} are the unique IDs of the input records. The values
     *     are in same order as {@code record}. In case of an error or a permission failure the
     *     HealthConnect service, {@link IInsertRecordsResponseCallback#onError} will be invoked
     *     with a {@link HealthConnectExceptionParcel}.
     */
    @Override
    public void insertRecords(
            @NonNull AttributionSource attributionSource,
            @NonNull RecordsParcel recordsParcel,
            @NonNull IInsertRecordsResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(false, INSERT_DATA)
                        .setPackageName(attributionSource.getPackageName());

        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        if (hasDataManagementPermission(uid, pid)) {
                            throw new SecurityException(
                                    "Apps with android.permission.MANAGE_HEALTH_DATA permission are"
                                            + " not allowed to insert records");
                        }
                        enforceMemoryRateLimit(
                                recordsParcel.getRecordsSize(),
                                recordsParcel.getRecordsChunkSize());
                        final List<RecordInternal<?>> recordInternals = recordsParcel.getRecords();
                        builder.setNumberOfRecords(recordInternals.size());
                        throwExceptionIfDataSyncInProgress();
                        mDataPermissionEnforcer.enforceRecordsWritePermissions(
                                recordInternals, attributionSource);
                        boolean isInForeground = mAppOpsManagerLocal.isUidInForeground(uid);
                        tryAcquireApiCallQuota(
                                uid, QuotaCategory.QUOTA_CATEGORY_WRITE, isInForeground, builder);
                        Trace.traceBegin(TRACE_TAG_INSERT, TAG_INSERT);
                        UpsertTransactionRequest insertRequest =
                                new UpsertTransactionRequest(
                                        attributionSource.getPackageName(),
                                        recordInternals,
                                        mContext,
                                        /* isInsertRequest */ true,
                                        mDataPermissionEnforcer
                                                .collectExtraWritePermissionStateMapping(
                                                        recordInternals, attributionSource));
                        List<String> uuids = mTransactionManager.insertAll(insertRequest);
                        tryAndReturnResult(callback, uuids, builder);

                        HealthConnectThreadScheduler.scheduleInternalTask(
                                () -> postInsertTasks(attributionSource, recordsParcel));

                        finishDataDeliveryWriteRecords(recordInternals, attributionSource);
                        logRecordTypeSpecificUpsertMetrics(
                                recordInternals, attributionSource.getPackageName());
                        builder.setDataTypesFromRecordInternals(recordInternals);
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception e) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, ERROR_INTERNAL);
                    } finally {
                        Trace.traceEnd(TRACE_TAG_INSERT);
                        builder.build().log();
                    }
                },
                uid,
                false);
    }

    private void postInsertTasks(
            @NonNull AttributionSource attributionSource, @NonNull RecordsParcel recordsParcel) {
        Trace.traceBegin(TRACE_TAG_INSERT_SUBTASKS, TAG_INSERT.concat("PostInsertTasks"));

        ActivityDateHelper.getInstance().insertRecordDate(recordsParcel.getRecords());
        Set<Integer> recordsTypesInsertedSet =
                recordsParcel.getRecords().stream()
                        .map(RecordInternal::getRecordType)
                        .collect(Collectors.toSet());
        // Update AppInfo table with the record types of records inserted in the request for the
        // current package.
        AppInfoHelper.getInstance()
                .updateAppInfoRecordTypesUsedOnInsert(
                        recordsTypesInsertedSet, attributionSource.getPackageName());

        Trace.traceEnd(TRACE_TAG_INSERT_SUBTASKS);
    }

    /**
     * Returns aggregation results based on the {@code request} into the HealthConnect database.
     *
     * @param request represents the request using which the aggregation is to be performed.
     * @param callback Callback to receive result of performing this operation.
     */
    public void aggregateRecords(
            @NonNull AttributionSource attributionSource,
            AggregateDataRequestParcel request,
            IAggregateRecordsResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final boolean holdsDataManagementPermission = hasDataManagementPermission(uid, pid);
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(
                                holdsDataManagementPermission, READ_AGGREGATED_DATA)
                        .setPackageName(attributionSource.getPackageName());

        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        builder.setNumberOfRecords(request.getAggregateIds().length);
                        throwExceptionIfDataSyncInProgress();
                        List<Integer> recordTypesToTest = new ArrayList<>();
                        for (int aggregateId : request.getAggregateIds()) {
                            recordTypesToTest.addAll(
                                    AggregationTypeIdMapper.getInstance()
                                            .getAggregationTypeFor(aggregateId)
                                            .getApplicableRecordTypeIds());
                        }

                        if (!holdsDataManagementPermission) {
                            boolean isInForeground = mAppOpsManagerLocal.isUidInForeground(uid);
                            if (!isInForeground) {
                                throwSecurityException(
                                        attributionSource.getPackageName()
                                                + "must be in foreground to call aggregate method");
                            }
                            mDataPermissionEnforcer.enforceRecordIdsReadPermissions(
                                    recordTypesToTest, attributionSource);
                            tryAcquireApiCallQuota(
                                    uid,
                                    RateLimiter.QuotaCategory.QUOTA_CATEGORY_READ,
                                    isInForeground,
                                    builder);
                        }
                        callback.onResult(
                                new AggregateTransactionRequest(
                                                attributionSource.getPackageName(), request)
                                        .getAggregateDataResponseParcel());
                        finishDataDeliveryRead(recordTypesToTest, attributionSource);
                        builder.setDataTypesFromRecordTypes(recordTypesToTest)
                                .setHealthDataServiceApiStatusSuccess();
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception e) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, ERROR_INTERNAL);
                    } finally {
                        builder.build().log();
                    }
                },
                uid,
                holdsDataManagementPermission);
    }

    /**
     * Read records {@code recordsParcel} from HealthConnect database.
     *
     * @param request ReadRecordsRequestParcel is parcel for the request object containing {@link
     *     RecordIdFiltersParcel}.
     * @param callback Callback to receive result of performing this operation. The records are
     *     returned in {@link RecordsParcel} . In case of an error or a permission failure the
     *     HealthConnect service, {@link IReadRecordsResponseCallback#onError} will be invoked with
     *     a {@link HealthConnectExceptionParcel}.
     */
    @Override
    public void readRecords(
            @NonNull AttributionSource attributionSource,
            @NonNull ReadRecordsRequestParcel request,
            @NonNull IReadRecordsResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final boolean holdsDataManagementPermission = hasDataManagementPermission(uid, pid);
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(holdsDataManagementPermission, READ_DATA)
                        .setPackageName(attributionSource.getPackageName());

        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        throwExceptionIfDataSyncInProgress();
                        AtomicBoolean enforceSelfRead = new AtomicBoolean();
                        if (!holdsDataManagementPermission) {
                            boolean isInForeground = mAppOpsManagerLocal.isUidInForeground(uid);
                            // If requesting app has only write permission allowed but no read
                            // permission for the record type or if app is not in foreground then
                            // allow to read its own records.
                            enforceSelfRead.set(
                                    mDataPermissionEnforcer.enforceReadAccessAndGetEnforceSelfRead(
                                                    request.getRecordType(), attributionSource)
                                            || !isInForeground);
                            if (Constants.DEBUG) {
                                Slog.d(
                                        TAG,
                                        "Enforce self read for package "
                                                + attributionSource.getPackageName()
                                                + ":"
                                                + enforceSelfRead.get());
                            }
                            tryAcquireApiCallQuota(
                                    uid,
                                    QuotaCategory.QUOTA_CATEGORY_READ,
                                    isInForeground,
                                    builder);
                        }
                        final Map<String, Boolean> extraReadPermsToGrantState =
                                Collections.unmodifiableMap(
                                        mDataPermissionEnforcer
                                                .collectExtraReadPermissionToStateMapping(
                                                        Set.of(request.getRecordType()),
                                                        attributionSource));

                        Trace.traceBegin(TRACE_TAG_READ, TAG_READ);
                        try {
                            long startDateAccess = request.getStartTime();
                            if (!holdsDataManagementPermission) {
                                Instant startInstant =
                                        mPermissionHelper.getHealthDataStartDateAccess(
                                                attributionSource.getPackageName(), userHandle);
                                if (startInstant == null) {
                                    throwExceptionIncorrectPermissionState();
                                }

                                // Always set the startDateAccess for local time filter, as for
                                // local date time we use it in conjunction with the time filter
                                // start-time
                                if (request.usesLocalTimeFilter()
                                        || startInstant.toEpochMilli() > startDateAccess) {
                                    startDateAccess = startInstant.toEpochMilli();
                                }
                            }
                            Pair<List<RecordInternal<?>>, Long> readRecordsResponse =
                                    mTransactionManager.readRecordsAndGetNextToken(
                                            new ReadTransactionRequest(
                                                    attributionSource.getPackageName(),
                                                    request,
                                                    startDateAccess,
                                                    enforceSelfRead.get(),
                                                    extraReadPermsToGrantState));
                            builder.setNumberOfRecords(readRecordsResponse.first.size());
                            long pageToken =
                                    request.getRecordIdFiltersParcel() == null
                                            ? readRecordsResponse.second
                                            : DEFAULT_LONG;
                            if (pageToken != DEFAULT_LONG) {
                                // pagetoken is used here to store sorting order of the result.
                                // An even pagetoken indicate ascending and Odd page token indicate
                                // descending sort order. This detail from page token will be used
                                // in next read request to have same sort order.
                                pageToken =
                                        request.isAscending() ? pageToken * 2 : pageToken * 2 + 1;
                            }

                            if (Constants.DEBUG) {
                                Slog.d(TAG, "pageToken: " + pageToken);
                            }

                            final String packageName = attributionSource.getPackageName();
                            final List<Integer> recordTypes =
                                    Collections.singletonList(request.getRecordType());
                            // Calls from controller APK should not be recorded in access logs
                            // If an app is reading only its own data then it is not recorded in
                            // access logs.
                            boolean requiresLogging =
                                    !holdsDataManagementPermission && !enforceSelfRead.get();
                            if (requiresLogging) {
                                Trace.traceBegin(
                                        TRACE_TAG_READ_SUBTASKS, TAG_READ.concat("AddAccessLog"));
                                AccessLogsHelper.getInstance()
                                        .addAccessLog(packageName, recordTypes, READ);
                                Trace.traceEnd(TRACE_TAG_READ_SUBTASKS);
                            }
                            callback.onResult(
                                    new ReadRecordsResponseParcel(
                                            new RecordsParcel(readRecordsResponse.first),
                                            pageToken));
                            finishDataDeliveryRead(request.getRecordType(), attributionSource);
                            if (requiresLogging) {
                                logRecordTypeSpecificReadMetrics(
                                        readRecordsResponse.first, packageName);
                            }
                            builder.setDataTypesFromRecordInternals(readRecordsResponse.first)
                                    .setHealthDataServiceApiStatusSuccess();
                        } catch (TypeNotPresentException exception) {
                            // All the requested package names are not present, so simply
                            // return an empty list
                            if (ReadTransactionRequest.TYPE_NOT_PRESENT_PACKAGE_NAME.equals(
                                    exception.typeName())) {
                                if (Constants.DEBUG) {
                                    Slog.d(
                                            TAG,
                                            "No app info recorded for "
                                                    + attributionSource.getPackageName());
                                }
                                callback.onResult(
                                        new ReadRecordsResponseParcel(
                                                new RecordsParcel(new ArrayList<>()),
                                                DEFAULT_LONG));
                                builder.setHealthDataServiceApiStatusSuccess();
                            } else {
                                builder.setHealthDataServiceApiStatusError(
                                        HealthConnectException.ERROR_UNKNOWN);
                                throw exception;
                            }
                        }
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (IllegalStateException illegalStateException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "IllegalStateException: ", illegalStateException);
                        tryAndThrowException(callback, illegalStateException, ERROR_INTERNAL);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception e) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, ERROR_INTERNAL);
                    } finally {
                        Trace.traceEnd(TRACE_TAG_READ);
                        builder.build().log();
                    }
                },
                uid,
                holdsDataManagementPermission);
    }

    /**
     * Updates {@code recordsParcel} into the HealthConnect database.
     *
     * @param recordsParcel parcel for list of records to be updated.
     * @param callback Callback to receive result of performing this operation. In case of an error
     *     or a permission failure the HealthConnect service, {@link IEmptyResponseCallback#onError}
     *     will be invoked with a {@link HealthConnectException}.
     */
    @Override
    public void updateRecords(
            @NonNull AttributionSource attributionSource,
            @NonNull RecordsParcel recordsParcel,
            @NonNull IEmptyResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(false, UPDATE_DATA)
                        .setPackageName(attributionSource.getPackageName());
        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        if (hasDataManagementPermission(uid, pid)) {
                            throw new SecurityException(
                                    "Apps with android.permission.MANAGE_HEALTH_DATA permission are"
                                            + " not allowed to insert records");
                        }
                        enforceMemoryRateLimit(
                                recordsParcel.getRecordsSize(),
                                recordsParcel.getRecordsChunkSize());
                        final List<RecordInternal<?>> recordInternals = recordsParcel.getRecords();
                        builder.setNumberOfRecords(recordInternals.size());
                        throwExceptionIfDataSyncInProgress();
                        mDataPermissionEnforcer.enforceRecordsWritePermissions(
                                recordInternals, attributionSource);
                        boolean isInForeground = mAppOpsManagerLocal.isUidInForeground(uid);
                        tryAcquireApiCallQuota(
                                uid, QuotaCategory.QUOTA_CATEGORY_WRITE, isInForeground, builder);
                        UpsertTransactionRequest request =
                                new UpsertTransactionRequest(
                                        attributionSource.getPackageName(),
                                        recordInternals,
                                        mContext,
                                        /* isInsertRequest */ false,
                                        mDataPermissionEnforcer
                                                .collectExtraWritePermissionStateMapping(
                                                        recordInternals, attributionSource));
                        mTransactionManager.updateAll(request);
                        tryAndReturnResult(callback, builder);
                        finishDataDeliveryWriteRecords(recordInternals, attributionSource);
                        logRecordTypeSpecificUpsertMetrics(
                                recordInternals, attributionSource.getPackageName());
                        builder.setDataTypesFromRecordInternals(recordInternals);
                        // Update activity dates table
                        HealthConnectThreadScheduler.scheduleInternalTask(
                                () ->
                                        ActivityDateHelper.getInstance()
                                                .reSyncByRecordTypeIds(
                                                        recordInternals.stream()
                                                                .map(RecordInternal::getRecordType)
                                                                .toList()));
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        Slog.e(TAG, "SqlException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (IllegalArgumentException illegalArgumentException) {
                        builder.setHealthDataServiceApiStatusError(
                                HealthConnectException.ERROR_INVALID_ARGUMENT);

                        Slog.e(TAG, "IllegalArgumentException: ", illegalArgumentException);
                        tryAndThrowException(
                                callback,
                                illegalArgumentException,
                                HealthConnectException.ERROR_INVALID_ARGUMENT);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception e) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);

                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, ERROR_INTERNAL);
                    } finally {
                        builder.build().log();
                    }
                },
                uid,
                false);
    }

    /**
     * @see HealthConnectManager#getChangeLogToken
     */
    @Override
    public void getChangeLogToken(
            @NonNull AttributionSource attributionSource,
            @NonNull ChangeLogTokenRequest request,
            @NonNull IGetChangeLogTokenCallback callback) {
        final int uid = Binder.getCallingUid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(false, GET_CHANGES_TOKEN)
                        .setPackageName(attributionSource.getPackageName());
        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        tryAcquireApiCallQuota(
                                uid,
                                QuotaCategory.QUOTA_CATEGORY_READ,
                                mAppOpsManagerLocal.isUidInForeground(uid),
                                builder);
                        throwExceptionIfDataSyncInProgress();
                        mDataPermissionEnforcer.enforceRecordIdsReadPermissions(
                                request.getRecordTypesList(), attributionSource);
                        callback.onResult(
                                new ChangeLogTokenResponse(
                                        ChangeLogsRequestHelper.getInstance()
                                                .getToken(
                                                        attributionSource.getPackageName(),
                                                        request)));
                        builder.setHealthDataServiceApiStatusSuccess();
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception e) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        tryAndThrowException(callback, e, ERROR_INTERNAL);
                    }
                    {
                        builder.build().log();
                    }
                },
                uid,
                false);
    }

    /**
     * @hide
     * @see HealthConnectManager#getChangeLogs
     */
    @Override
    public void getChangeLogs(
            @NonNull AttributionSource attributionSource,
            @NonNull ChangeLogsRequest token,
            IChangeLogsResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final String callerPackageName = Objects.requireNonNull(attributionSource.getPackageName());
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(false, GET_CHANGES)
                        .setPackageName(callerPackageName);

        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        throwExceptionIfDataSyncInProgress();
                        ChangeLogsRequestHelper.TokenRequest changeLogsTokenRequest =
                                ChangeLogsRequestHelper.getRequest(
                                        attributionSource.getPackageName(), token.getToken());
                        mDataPermissionEnforcer.enforceRecordIdsReadPermissions(
                                changeLogsTokenRequest.getRecordTypes(), attributionSource);
                        boolean isInForeground = mAppOpsManagerLocal.isUidInForeground(uid);
                        if (!isInForeground) {
                            throwSecurityException(
                                    attributionSource.getPackageName()
                                            + " must be in foreground to read the change logs");
                        }
                        tryAcquireApiCallQuota(
                                uid, QuotaCategory.QUOTA_CATEGORY_READ, isInForeground, builder);
                        Instant startDateInstant =
                                mPermissionHelper.getHealthDataStartDateAccess(
                                        attributionSource.getPackageName(), userHandle);
                        if (startDateInstant == null) {
                            throwExceptionIncorrectPermissionState();
                        }
                        long startDateAccess = startDateInstant.toEpochMilli();
                        final ChangeLogsHelper.ChangeLogsResponse changeLogsResponse =
                                ChangeLogsHelper.getInstance()
                                        .getChangeLogs(changeLogsTokenRequest, token);

                        Map<Integer, List<UUID>> recordTypeToInsertedUuids =
                                ChangeLogsHelper.getRecordTypeToInsertedUuids(
                                        changeLogsResponse.getChangeLogsMap());

                        Map<String, Boolean> extraReadPermsToGrantState =
                                mDataPermissionEnforcer.collectExtraReadPermissionToStateMapping(
                                        recordTypeToInsertedUuids.keySet(), attributionSource);

                        List<RecordInternal<?>> recordInternals =
                                mTransactionManager.readRecords(
                                        new ReadTransactionRequest(
                                                callerPackageName,
                                                recordTypeToInsertedUuids,
                                                startDateAccess,
                                                extraReadPermsToGrantState));

                        List<DeletedLog> deletedLogs =
                                ChangeLogsHelper.getDeletedLogs(
                                        changeLogsResponse.getChangeLogsMap());

                        callback.onResult(
                                new ChangeLogsResponse(
                                        new RecordsParcel(recordInternals),
                                        deletedLogs,
                                        changeLogsResponse.getNextPageToken(),
                                        changeLogsResponse.hasMorePages()));
                        finishDataDeliveryRead(
                                changeLogsTokenRequest.getRecordTypes(), attributionSource);
                        builder.setHealthDataServiceApiStatusSuccess()
                                .setNumberOfRecords(recordInternals.size() + deletedLogs.size())
                                .setDataTypesFromRecordInternals(recordInternals);
                    } catch (IllegalArgumentException illegalArgumentException) {
                        builder.setHealthDataServiceApiStatusError(
                                HealthConnectException.ERROR_INVALID_ARGUMENT);
                        Slog.e(TAG, "IllegalArgumentException: ", illegalArgumentException);
                        tryAndThrowException(
                                callback,
                                illegalArgumentException,
                                HealthConnectException.ERROR_INVALID_ARGUMENT);
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (IllegalStateException illegalStateException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "IllegalStateException: ", illegalStateException);
                        tryAndThrowException(callback, illegalStateException, ERROR_INTERNAL);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "Exception: ", exception);
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    } finally {
                        builder.build().log();
                    }
                },
                uid,
                false);
    }

    /**
     * API to delete records based on {@code request}
     *
     * <p>NOTE: Though internally we only need a single API to handle deletes as SDK code transform
     * all its delete requests to {@link DeleteUsingFiltersRequestParcel}, we have this separation
     * to make sure no non-controller APIs can use {@link
     * HealthConnectServiceImpl#deleteUsingFilters} API
     */
    @Override
    public void deleteUsingFiltersForSelf(
            @NonNull AttributionSource attributionSource,
            @NonNull DeleteUsingFiltersRequestParcel request,
            @NonNull IEmptyResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final boolean holdsDataManagementPermission = hasDataManagementPermission(uid, pid);
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(holdsDataManagementPermission, DELETE_DATA)
                        .setPackageName(attributionSource.getPackageName());

        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        throwExceptionIfDataSyncInProgress();
                        List<Integer> recordTypeIdsToDelete =
                                (!request.getRecordTypeFilters().isEmpty())
                                        ? request.getRecordTypeFilters()
                                        : new ArrayList<>(
                                                RecordMapper.getInstance()
                                                        .getRecordIdToExternalRecordClassMap()
                                                        .keySet());
                        // Requests from non controller apps are not allowed to use non-id
                        // filters
                        request.setPackageNameFilters(
                                Collections.singletonList(attributionSource.getPackageName()));

                        if (!holdsDataManagementPermission) {
                            mDataPermissionEnforcer.enforceRecordIdsWritePermissions(
                                    recordTypeIdsToDelete, attributionSource);
                            tryAcquireApiCallQuota(
                                    uid,
                                    QuotaCategory.QUOTA_CATEGORY_WRITE,
                                    mAppOpsManagerLocal.isUidInForeground(uid),
                                    builder);
                        }

                        deleteUsingFiltersInternal(
                                attributionSource,
                                request,
                                callback,
                                builder,
                                recordTypeIdsToDelete,
                                uid,
                                pid);
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (IllegalArgumentException illegalArgumentException) {
                        builder.setHealthDataServiceApiStatusError(
                                HealthConnectException.ERROR_INVALID_ARGUMENT);
                        Slog.e(TAG, "IllegalArgumentException: ", illegalArgumentException);
                        tryAndThrowException(
                                callback,
                                illegalArgumentException,
                                HealthConnectException.ERROR_INVALID_ARGUMENT);
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "Exception: ", exception);
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    } finally {
                        builder.build().log();
                    }
                },
                uid,
                holdsDataManagementPermission);
    }

    /**
     * API to delete records based on {@code request}
     *
     * <p>NOTE: Though internally we only need a single API to handle deletes as SDK code transform
     * all its delete requests to {@link DeleteUsingFiltersRequestParcel}, we have this separation
     * to make sure no non-controller APIs can use this API
     */
    @Override
    public void deleteUsingFilters(
            @NonNull AttributionSource attributionSource,
            @NonNull DeleteUsingFiltersRequestParcel request,
            @NonNull IEmptyResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        final boolean holdsDataManagementPermission = hasDataManagementPermission(uid, pid);
        final HealthConnectServiceLogger.Builder builder =
                new HealthConnectServiceLogger.Builder(holdsDataManagementPermission, DELETE_DATA)
                        .setPackageName(attributionSource.getPackageName());

        HealthConnectThreadScheduler.schedule(
                mContext,
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        verifyPackageNameFromUid(uid, attributionSource);
                        throwExceptionIfDataSyncInProgress();
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        List<Integer> recordTypeIdsToDelete =
                                (!request.getRecordTypeFilters().isEmpty())
                                        ? request.getRecordTypeFilters()
                                        : new ArrayList<>(
                                                RecordMapper.getInstance()
                                                        .getRecordIdToExternalRecordClassMap()
                                                        .keySet());

                        deleteUsingFiltersInternal(
                                attributionSource,
                                request,
                                callback,
                                builder,
                                recordTypeIdsToDelete,
                                uid,
                                pid);
                    } catch (SQLiteException sqLiteException) {
                        builder.setHealthDataServiceApiStatusError(HealthConnectException.ERROR_IO);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (IllegalArgumentException illegalArgumentException) {
                        builder.setHealthDataServiceApiStatusError(
                                HealthConnectException.ERROR_INVALID_ARGUMENT);
                        Slog.e(TAG, "IllegalArgumentException: ", illegalArgumentException);
                        tryAndThrowException(
                                callback,
                                illegalArgumentException,
                                HealthConnectException.ERROR_INVALID_ARGUMENT);
                    } catch (SecurityException securityException) {
                        builder.setHealthDataServiceApiStatusError(ERROR_SECURITY);
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        builder.setHealthDataServiceApiStatusError(
                                healthConnectException.getErrorCode());
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
                        Slog.e(TAG, "Exception: ", exception);
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    } finally {
                        builder.build().log();
                    }
                },
                uid,
                holdsDataManagementPermission);
    }

    private void deleteUsingFiltersInternal(
            @NonNull AttributionSource attributionSource,
            @NonNull DeleteUsingFiltersRequestParcel request,
            @NonNull IEmptyResponseCallback callback,
            @NonNull HealthConnectServiceLogger.Builder builder,
            List<Integer> recordTypeIdsToDelete,
            int uid,
            int pid) {
        if (request.usesIdFilters() && request.usesNonIdFilters()) {
            throw new IllegalArgumentException(
                    "Requests with both id and non-id filters are not" + " supported");
        }
        int numberOfRecordsDeleted =
                mTransactionManager.deleteAll(
                        new DeleteTransactionRequest(attributionSource.getPackageName(), request)
                                .setHasManageHealthDataPermission(
                                        hasDataManagementPermission(uid, pid)));
        tryAndReturnResult(callback, builder);
        finishDataDeliveryWrite(recordTypeIdsToDelete, attributionSource);
        HealthConnectThreadScheduler.scheduleInternalTask(
                () -> postDeleteTasks(recordTypeIdsToDelete));

        builder.setNumberOfRecords(numberOfRecordsDeleted)
                .setDataTypesFromRecordTypes(recordTypeIdsToDelete);
    }

    /** API to get Priority for {@code dataCategory} */
    @Override
    public void getCurrentPriority(
            @NonNull String packageName,
            @HealthDataCategory.Type int dataCategory,
            @NonNull IGetPriorityResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        HealthConnectThreadScheduler.scheduleControllerTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        throwExceptionIfDataSyncInProgress();
                        List<DataOrigin> dataOriginInPriorityOrder =
                                HealthDataCategoryPriorityHelper.getInstance()
                                        .getPriorityOrder(dataCategory)
                                        .stream()
                                        .map(
                                                (name) ->
                                                        new DataOrigin.Builder()
                                                                .setPackageName(name)
                                                                .build())
                                        .collect(Collectors.toList());
                        callback.onResult(
                                new GetPriorityResponseParcel(
                                        new FetchDataOriginsPriorityOrderResponse(
                                                dataOriginInPriorityOrder)));
                    } catch (SQLiteException sqLiteException) {
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        Slog.e(TAG, "Exception: ", exception);
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    }
                });
    }

    /** API to update priority for permission category(ies) */
    @Override
    public void updatePriority(
            @NonNull String packageName,
            @NonNull UpdatePriorityRequestParcel updatePriorityRequest,
            @NonNull IEmptyResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        HealthConnectThreadScheduler.scheduleControllerTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        throwExceptionIfDataSyncInProgress();
                        HealthDataCategoryPriorityHelper.getInstance()
                                .setPriorityOrder(
                                        updatePriorityRequest.getDataCategory(),
                                        updatePriorityRequest.getPackagePriorityOrder());
                        callback.onResult();
                    } catch (SQLiteException sqLiteException) {
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        Slog.e(TAG, "Exception: ", exception);
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    }
                });
    }

    @Override
    public void setRecordRetentionPeriodInDays(
            int days, @NonNull UserHandle user, IEmptyResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        HealthConnectThreadScheduler.scheduleControllerTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        throwExceptionIfDataSyncInProgress();
                        AutoDeleteService.setRecordRetentionPeriodInDays(days);
                        callback.onResult();
                    } catch (SQLiteException sqLiteException) {
                        Slog.e(TAG, "SQLiteException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        Slog.e(TAG, "Exception: ", exception);
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    }
                });
    }

    @Override
    public int getRecordRetentionPeriodInDays(@NonNull UserHandle user) {
        enforceIsForegroundUser(getCallingUserHandle());
        throwExceptionIfDataSyncInProgress();
        try {
            mContext.enforceCallingPermission(MANAGE_HEALTH_DATA_PERMISSION, null);
            return AutoDeleteService.getRecordRetentionPeriodInDays();
        } catch (Exception e) {
            if (e instanceof SecurityException) {
                throw e;
            }
            Slog.e(TAG, "Unable to get record retention period for " + user);
        }

        throw new RuntimeException();
    }

    /**
     * Returns information, represented by {@code ApplicationInfoResponse}, for all the packages
     * that have contributed to the health connect DB.
     *
     * @param callback Callback to receive result of performing this operation. In case of an error
     *     or a permission failure the HealthConnect service, {@link IEmptyResponseCallback#onError}
     *     will be invoked with a {@link HealthConnectException}.
     */
    @Override
    public void getContributorApplicationsInfo(@NonNull IApplicationInfoResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        HealthConnectThreadScheduler.scheduleControllerTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        throwExceptionIfDataSyncInProgress();
                        List<AppInfo> applicationInfos =
                                AppInfoHelper.getInstance().getApplicationInfosWithRecordTypes();

                        callback.onResult(new ApplicationInfoResponseParcel(applicationInfos));
                    } catch (SQLiteException sqLiteException) {
                        Slog.e(TAG, "SqlException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, ERROR_INTERNAL);
                    }
                });
    }

    /** Retrieves {@link RecordTypeInfoResponse} for each RecordType. */
    @Override
    public void queryAllRecordTypesInfo(@NonNull IRecordTypeInfoResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        HealthConnectThreadScheduler.scheduleControllerTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        throwExceptionIfDataSyncInProgress();
                        callback.onResult(
                                new RecordTypeInfoResponseParcel(
                                        getPopulatedRecordTypeInfoResponses()));
                    } catch (SQLiteException sqLiteException) {
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    }
                });
    }

    /**
     * @see HealthConnectManager#queryAccessLogs
     */
    @Override
    public void queryAccessLogs(@NonNull String packageName, IAccessLogsResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();

        HealthConnectThreadScheduler.scheduleControllerTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        throwExceptionIfDataSyncInProgress();
                        final List<AccessLog> accessLogsList =
                                AccessLogsHelper.getInstance().queryAccessLogs();
                        callback.onResult(new AccessLogsResponseParcel(accessLogsList));
                    } catch (SecurityException securityException) {
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception exception) {
                        Slog.e(TAG, "Exception: ", exception);
                        tryAndThrowException(callback, exception, ERROR_INTERNAL);
                    }
                });
    }

    /**
     * Returns a list of unique dates for which the database has at least one entry
     *
     * @param activityDatesRequestParcel Parcel request containing records classes
     * @param callback Callback to receive result of performing this operation. The results are
     *     returned in {@link List<LocalDate>} . In case of an error or a permission failure the
     *     HealthConnect service, {@link IActivityDatesResponseCallback#onError} will be invoked
     *     with a {@link HealthConnectExceptionParcel}.
     */
    @Override
    public void getActivityDates(
            @NonNull ActivityDatesRequestParcel activityDatesRequestParcel,
            IActivityDatesResponseCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();

        HealthConnectThreadScheduler.scheduleControllerTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);
                        throwExceptionIfDataSyncInProgress();
                        List<LocalDate> localDates =
                                ActivityDateHelper.getInstance()
                                        .getActivityDates(
                                                activityDatesRequestParcel.getRecordTypes());

                        callback.onResult(new ActivityDatesResponseParcel(localDates));
                    } catch (SQLiteException sqLiteException) {
                        Slog.e(TAG, "SqlException: ", sqLiteException);
                        tryAndThrowException(
                                callback, sqLiteException, HealthConnectException.ERROR_IO);
                    } catch (SecurityException securityException) {
                        Slog.e(TAG, "SecurityException: ", securityException);
                        tryAndThrowException(callback, securityException, ERROR_SECURITY);
                    } catch (HealthConnectException healthConnectException) {
                        Slog.e(TAG, "HealthConnectException: ", healthConnectException);
                        tryAndThrowException(
                                callback,
                                healthConnectException,
                                healthConnectException.getErrorCode());
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, ERROR_INTERNAL);
                    }
                });
    }

    // TODO(b/265780725): Update javadocs and ensure that the caller handles SHOW_MIGRATION_INFO
    // intent.
    @Override
    public void startMigration(@NonNull String packageName, IMigrationCallback callback) {
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();

        HealthConnectThreadScheduler.scheduleInternalTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(
                                MIGRATE_HEALTH_CONNECT_DATA,
                                pid,
                                uid,
                                "Caller does not have " + MIGRATE_HEALTH_CONNECT_DATA);
                        enforceShowMigrationInfoIntent(packageName, uid);
                        mBackupRestore.runWithStatesReadLock(
                                () -> {
                                    if (mBackupRestore.isRestoreMergingInProgress()) {
                                        throw new MigrationException(
                                                "Cannot start data migration. Backup and restore in"
                                                        + " progress.",
                                                MigrationException.ERROR_INTERNAL,
                                                null);
                                    }
                                    mMigrationStateManager.startMigration(mContext);
                                });
                        PriorityMigrationHelper.getInstance().populatePreMigrationPriority();
                        callback.onSuccess();
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, MigrationException.ERROR_INTERNAL, null);
                    }
                });
    }

    // TODO(b/265780725): Update javadocs and ensure that the caller handles SHOW_MIGRATION_INFO
    // intent.
    @Override
    public void finishMigration(@NonNull String packageName, IMigrationCallback callback) {
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();

        HealthConnectThreadScheduler.scheduleInternalTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(
                                MIGRATE_HEALTH_CONNECT_DATA,
                                pid,
                                uid,
                                "Caller does not have " + MIGRATE_HEALTH_CONNECT_DATA);
                        enforceShowMigrationInfoIntent(packageName, uid);
                        mMigrationStateManager.finishMigration(mContext);
                        AppInfoHelper.getInstance().syncAppInfoRecordTypesUsed();
                        callback.onSuccess();
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception: ", e);
                        // TODO(b/263897830): Verify migration state and send errors properly
                        tryAndThrowException(callback, e, MigrationException.ERROR_INTERNAL, null);
                    }
                });
    }

    // TODO(b/265780725): Update javadocs and ensure that the caller handles SHOW_MIGRATION_INFO
    // intent.
    @Override
    public void writeMigrationData(
            @NonNull String packageName,
            MigrationEntityParcel parcel,
            IMigrationCallback callback) {
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        UserHandle callingUserHandle = getCallingUserHandle();

        HealthConnectThreadScheduler.scheduleInternalTask(
                () -> {
                    try {
                        enforceIsForegroundUser(callingUserHandle);
                        mContext.enforcePermission(
                                MIGRATE_HEALTH_CONNECT_DATA,
                                pid,
                                uid,
                                "Caller does not have " + MIGRATE_HEALTH_CONNECT_DATA);
                        enforceShowMigrationInfoIntent(packageName, uid);
                        mMigrationStateManager.validateWriteMigrationData();
                        getDataMigrationManager(callingUserHandle)
                                .apply(parcel.getMigrationEntities());
                        callback.onSuccess();
                    } catch (DataMigrationManager.EntityWriteException e) {
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(
                                callback,
                                e,
                                MigrationException.ERROR_MIGRATE_ENTITY,
                                e.getEntityId());
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, MigrationException.ERROR_INTERNAL, null);
                    }
                });
    }

    public void insertMinDataMigrationSdkExtensionVersion(
            @NonNull String packageName, int requiredSdkExtension, IMigrationCallback callback) {
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();

        HealthConnectThreadScheduler.scheduleInternalTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(
                                MIGRATE_HEALTH_CONNECT_DATA,
                                pid,
                                uid,
                                "Caller does not have " + MIGRATE_HEALTH_CONNECT_DATA);
                        enforceShowMigrationInfoIntent(packageName, uid);
                        mMigrationStateManager.validateSetMinSdkVersion();
                        mMigrationStateManager.setMinDataMigrationSdkExtensionVersion(
                                mContext, requiredSdkExtension);

                        callback.onSuccess();
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception: ", e);
                        tryAndThrowException(callback, e, MigrationException.ERROR_INTERNAL, null);
                    }
                });
    }

    /**
     * @see HealthConnectManager#stageAllHealthConnectRemoteData
     */
    @Override
    public void stageAllHealthConnectRemoteData(
            @NonNull StageRemoteDataRequest stageRemoteDataRequest,
            @NonNull UserHandle userHandle,
            @NonNull IDataStagingFinishedCallback callback) {
        Map<String, ParcelFileDescriptor> origPfdsByFileName =
                stageRemoteDataRequest.getPfdsByFileName();
        Map<String, HealthConnectException> exceptionsByFileName =
                new ArrayMap<>(origPfdsByFileName.size());
        Map<String, ParcelFileDescriptor> pfdsByFileName =
                new ArrayMap<>(origPfdsByFileName.size());

        try {
            mDataPermissionEnforcer.enforceAnyOfPermissions(
                    Manifest.permission.STAGE_HEALTH_CONNECT_REMOTE_DATA,
                    HEALTH_CONNECT_BACKUP_INTER_AGENT_PERMISSION);

            enforceIsForegroundUser(Binder.getCallingUserHandle());

            for (Entry<String, ParcelFileDescriptor> entry : origPfdsByFileName.entrySet()) {
                try {
                    pfdsByFileName.put(entry.getKey(), entry.getValue().dup());
                } catch (IOException e) {
                    Slog.e(TAG, "IOException: ", e);
                    exceptionsByFileName.put(
                            entry.getKey(),
                            new HealthConnectException(
                                    HealthConnectException.ERROR_IO, e.getMessage()));
                }
            }

            HealthConnectThreadScheduler.scheduleInternalTask(
                    () -> {
                        if (!mBackupRestore.prepForStagingIfNotAlreadyDone()) {
                            try {
                                callback.onResult();
                            } catch (RemoteException e) {
                                Log.e(TAG, "Restore response could not be sent to the caller.", e);
                            }
                            return;
                        }
                        mBackupRestore.stageAllHealthConnectRemoteData(
                                pfdsByFileName,
                                exceptionsByFileName,
                                userHandle.getIdentifier(),
                                callback);
                    });
        } catch (SecurityException | IllegalStateException e) {
            Log.e(TAG, "Exception encountered while staging", e);
            try {
                @HealthConnectException.ErrorCode
                int errorCode = (e instanceof SecurityException) ? ERROR_SECURITY : ERROR_INTERNAL;
                exceptionsByFileName.put("", new HealthConnectException(errorCode, e.getMessage()));

                callback.onError(new StageRemoteDataException(exceptionsByFileName));
            } catch (RemoteException remoteException) {
                Log.e(TAG, "Restore permission response could not be sent to the caller.", e);
            }
        }
    }

    /**
     * @see HealthConnectManager#getAllDataForBackup
     */
    @Override
    public void getAllDataForBackup(
            @NonNull StageRemoteDataRequest stageRemoteDataRequest,
            @NonNull UserHandle userHandle) {
        mContext.enforceCallingPermission(HEALTH_CONNECT_BACKUP_INTER_AGENT_PERMISSION, null);
        mBackupRestore.getAllDataForBackup(stageRemoteDataRequest, userHandle);
    }

    /**
     * @see HealthConnectManager#getAllBackupFileNames
     */
    @Override
    public BackupFileNamesSet getAllBackupFileNames(boolean forDeviceToDevice) {
        mContext.enforceCallingPermission(HEALTH_CONNECT_BACKUP_INTER_AGENT_PERMISSION, null);
        return mBackupRestore.getAllBackupFileNames(forDeviceToDevice);
    }

    /**
     * @see HealthConnectManager#deleteAllStagedRemoteData
     */
    @Override
    public void deleteAllStagedRemoteData(@NonNull UserHandle userHandle) {
        mContext.enforceCallingPermission(
                DELETE_STAGED_HEALTH_CONNECT_REMOTE_DATA_PERMISSION, null);
        mBackupRestore.deleteAndResetEverything(userHandle);
        mMigrationStateManager.clearCaches(mContext);
        AppInfoHelper.getInstance().clearData(mTransactionManager);
        ActivityDateHelper.getInstance().clearData(mTransactionManager);
        MigrationEntityHelper.getInstance().clearData(mTransactionManager);
        HealthDataCategoryPriorityHelper.getInstance().clearData(mTransactionManager);
        PriorityMigrationHelper.getInstance().clearData(mTransactionManager);
        RateLimiter.clearCache();
        String[] packageNames = mContext.getPackageManager().getPackagesForUid(getCallingUid());
        for (String packageName : packageNames) {
            mFirstGrantTimeManager.setFirstGrantTime(packageName, Instant.now(), userHandle);
        }
    }

    /**
     * @see HealthConnectManager#updateDataDownloadState
     */
    @Override
    public void updateDataDownloadState(@DataDownloadState int downloadState) {
        mContext.enforceCallingPermission(
                Manifest.permission.STAGE_HEALTH_CONNECT_REMOTE_DATA, null);
        enforceIsForegroundUser(getCallingUserHandle());
        mBackupRestore.updateDataDownloadState(downloadState);
    }

    /**
     * @see HealthConnectManager#getHealthConnectDataState
     */
    @Override
    public void getHealthConnectDataState(@NonNull IGetHealthConnectDataStateCallback callback) {
        try {
            mDataPermissionEnforcer.enforceAnyOfPermissions(
                    MANAGE_HEALTH_DATA_PERMISSION, Manifest.permission.MIGRATE_HEALTH_CONNECT_DATA);
            final UserHandle userHandle = Binder.getCallingUserHandle();
            enforceIsForegroundUser(userHandle);
            HealthConnectThreadScheduler.scheduleInternalTask(
                    () -> {
                        try {
                            @HealthConnectDataState.DataRestoreError
                            int dataRestoreError = mBackupRestore.getDataRestoreError();
                            @HealthConnectDataState.DataRestoreState
                            int dataRestoreState = mBackupRestore.getDataRestoreState();

                            try {
                                callback.onResult(
                                        new HealthConnectDataState(
                                                dataRestoreState,
                                                dataRestoreError,
                                                mMigrationStateManager.getMigrationState()));
                            } catch (RemoteException remoteException) {
                                Log.e(
                                        TAG,
                                        "HealthConnectDataState could not be sent to the caller.",
                                        remoteException);
                            }
                        } catch (RuntimeException e) {
                            // exception getting the state from the disk
                            try {
                                callback.onError(
                                        new HealthConnectExceptionParcel(
                                                new HealthConnectException(
                                                        HealthConnectException.ERROR_IO,
                                                        e.getMessage())));
                            } catch (RemoteException remoteException) {
                                Log.e(
                                        TAG,
                                        "Exception for getHealthConnectDataState could not be sent"
                                                + " to the caller.",
                                        remoteException);
                            }
                        }
                    });
        } catch (SecurityException | IllegalStateException e) {
            Log.e(TAG, "getHealthConnectDataState: Exception encountered", e);
            @HealthConnectException.ErrorCode
            int errorCode = (e instanceof SecurityException) ? ERROR_SECURITY : ERROR_INTERNAL;
            try {
                callback.onError(
                        new HealthConnectExceptionParcel(
                                new HealthConnectException(errorCode, e.getMessage())));
            } catch (RemoteException remoteException) {
                Log.e(TAG, "getHealthConnectDataState error could not be sent", e);
            }
        }
    }

    /**
     * @see HealthConnectManager#getHealthConnectMigrationUiState
     */
    @Override
    public void getHealthConnectMigrationUiState(
            @NonNull IGetHealthConnectMigrationUiStateCallback callback) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final UserHandle userHandle = Binder.getCallingUserHandle();
        HealthConnectThreadScheduler.scheduleInternalTask(
                () -> {
                    try {
                        enforceIsForegroundUser(userHandle);
                        mContext.enforcePermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid, null);

                        try {
                            callback.onResult(
                                    new HealthConnectMigrationUiState(
                                            mMigrationUiStateManager
                                                    .getHealthConnectMigrationUiState()));
                        } catch (RemoteException remoteException) {
                            Log.e(
                                    TAG,
                                    "HealthConnectMigrationUiState could not be sent to the"
                                            + " caller.",
                                    remoteException);
                        }
                    } catch (SecurityException securityException) {
                        try {
                            callback.onError(
                                    new HealthConnectExceptionParcel(
                                            new HealthConnectException(
                                                    ERROR_SECURITY,
                                                    securityException.getMessage())));
                        } catch (RemoteException remoteException) {
                            Log.e(
                                    TAG,
                                    "Exception for HealthConnectMigrationUiState could not be sent"
                                            + " to the caller.",
                                    remoteException);
                        }
                    } catch (RuntimeException e) {
                        // exception getting the state from the disk
                        try {
                            callback.onError(
                                    new HealthConnectExceptionParcel(
                                            new HealthConnectException(
                                                    HealthConnectException.ERROR_IO,
                                                    e.getMessage())));
                        } catch (RemoteException remoteException) {
                            Log.e(
                                    TAG,
                                    "Exception for HealthConnectMigrationUiState could not be sent"
                                            + " to the caller.",
                                    remoteException);
                        }
                    }
                });
    }

    // Cancel BR timeouts - this might be needed when a user is going into background.
    void cancelBackupRestoreTimeouts() {
        mBackupRestore.cancelAllJobs();
    }

    private void tryAcquireApiCallQuota(
            int uid,
            @QuotaCategory.Type int quotaCategory,
            boolean isInForeground,
            HealthConnectServiceLogger.Builder builder) {
        try {
            RateLimiter.tryAcquireApiCallQuota(uid, quotaCategory, isInForeground);
        } catch (RateLimiterException rateLimiterException) {
            builder.setRateLimit(
                    rateLimiterException.getRateLimiterQuotaBucket(),
                    rateLimiterException.getRateLimiterQuotaLimit());
            throw new HealthConnectException(
                    rateLimiterException.getErrorCode(), rateLimiterException.getMessage());
        }
    }

    private void enforceMemoryRateLimit(List<Long> recordsSize, long recordsChunkSize) {
        recordsSize.forEach(RateLimiter::checkMaxRecordMemoryUsage);
        RateLimiter.checkMaxChunkMemoryUsage(recordsChunkSize);
    }

    private void enforceIsForegroundUser(UserHandle callingUserHandle) {
        if (!callingUserHandle.equals(mCurrentForegroundUser)) {
            throw new IllegalStateException(
                    "Calling user: "
                            + callingUserHandle.getIdentifier()
                            + "is not the current foreground user: "
                            + mCurrentForegroundUser.getIdentifier()
                            + ". HC request must be called"
                            + " from the current foreground user.");
        }
    }

    private boolean isDataSyncInProgress() {
        return mMigrationStateManager.isMigrationInProgress()
                || mBackupRestore.isRestoreMergingInProgress();
    }

    @VisibleForTesting
    Set<String> getStagedRemoteFileNames(int userId) {
        return mBackupRestore.getStagedRemoteFileNames(userId);
    }

    @NonNull
    private DataMigrationManager getDataMigrationManager(@NonNull UserHandle userHandle) {
        final Context userContext = mContext.createContextAsUser(userHandle, 0);

        return new DataMigrationManager(
                userContext,
                mTransactionManager,
                mPermissionHelper,
                mFirstGrantTimeManager,
                DeviceInfoHelper.getInstance(),
                AppInfoHelper.getInstance(),
                MigrationEntityHelper.getInstance(),
                RecordHelperProvider.getInstance(),
                HealthDataCategoryPriorityHelper.getInstance(),
                PriorityMigrationHelper.getInstance(),
                ActivityDateHelper.getInstance());
    }

    private void enforceCallingPackageBelongsToUid(String packageName, int callingUid) {
        int packageUid;
        try {
            packageUid =
                    mContext.getPackageManager()
                            .getPackageUid(
                                    packageName, /* flags */ PackageManager.PackageInfoFlags.of(0));
        } catch (PackageManager.NameNotFoundException e) {
            throw new IllegalStateException(packageName + " not found");
        }
        if (UserHandle.getAppId(packageUid) != UserHandle.getAppId(callingUid)) {
            throwSecurityException(packageName + " does not belong to uid " + callingUid);
        }
    }

    /**
     * Verify various aspects of the calling user.
     *
     * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
     * @param callerAttributionSource The permission identity of the caller
     */
    private void verifyPackageNameFromUid(
            int callingUid, @NonNull AttributionSource callerAttributionSource) {
        // Check does the attribution source is one for the calling app.
        callerAttributionSource.enforceCallingUid();
        // Obtain the user where the client is running in.
        UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
        Context callingUserContext = mContext.createContextAsUser(callingUserHandle, 0);
        String callingPackageName =
                Objects.requireNonNull(callerAttributionSource.getPackageName());
        verifyCallingPackage(callingUserContext, callingUid, callingPackageName);
    }

    /**
     * Check that the caller's supposed package name matches the uid making the call.
     *
     * @throws SecurityException if the package name and uid don't match.
     */
    private void verifyCallingPackage(
            @NonNull Context actualCallingUserContext,
            int actualCallingUid,
            @NonNull String claimedCallingPackage) {
        int claimedCallingUid = getPackageUid(actualCallingUserContext, claimedCallingPackage);
        if (claimedCallingUid != actualCallingUid) {
            throwSecurityException(
                    claimedCallingPackage + " does not belong to uid " + actualCallingUid);
        }
    }

    /** Finds the UID of the {@code packageName} in the given {@code context}. */
    private int getPackageUid(@NonNull Context context, @NonNull String packageName) {
        try {
            return context.getPackageManager().getPackageUid(packageName, /* flags= */ 0);
        } catch (PackageManager.NameNotFoundException e) {
            return Process.INVALID_UID;
        }
    }

    private void enforceShowMigrationInfoIntent(String packageName, int callingUid) {
        enforceCallingPackageBelongsToUid(packageName, callingUid);

        Intent intentToCheck =
                new Intent(HealthConnectManager.ACTION_SHOW_MIGRATION_INFO).setPackage(packageName);

        ResolveInfo resolveResult =
                mContext.getPackageManager()
                        .resolveActivity(
                                intentToCheck,
                                PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_ALL));

        if (Objects.isNull(resolveResult)) {
            throw new IllegalArgumentException(
                    packageName
                            + " does not handle intent "
                            + HealthConnectManager.ACTION_SHOW_MIGRATION_INFO);
        }
    }

    private Map<Integer, List<DataOrigin>> getPopulatedRecordTypeInfoResponses() {
        Map<Integer, Class<? extends Record>> recordIdToExternalRecordClassMap =
                RecordMapper.getInstance().getRecordIdToExternalRecordClassMap();
        AppInfoHelper appInfoHelper = AppInfoHelper.getInstance();
        Map<Integer, List<DataOrigin>> recordTypeInfoResponses =
                new ArrayMap<>(recordIdToExternalRecordClassMap.size());
        Map<Integer, Set<String>> recordTypeToContributingPackagesMap =
                appInfoHelper.getRecordTypesToContributingPackagesMap();
        recordIdToExternalRecordClassMap
                .keySet()
                .forEach(
                        (recordType) -> {
                            if (recordTypeToContributingPackagesMap.containsKey(recordType)) {
                                List<DataOrigin> packages =
                                        recordTypeToContributingPackagesMap.get(recordType).stream()
                                                .map(
                                                        (packageName) ->
                                                                new DataOrigin.Builder()
                                                                        .setPackageName(packageName)
                                                                        .build())
                                                .toList();
                                recordTypeInfoResponses.put(recordType, packages);
                            } else {
                                recordTypeInfoResponses.put(recordType, Collections.emptyList());
                            }
                        });
        return recordTypeInfoResponses;
    }

    private boolean hasDataManagementPermission(int uid, int pid) {
        return mContext.checkPermission(MANAGE_HEALTH_DATA_PERMISSION, pid, uid)
                == PERMISSION_GRANTED;
    }

    private void finishDataDeliveryRead(int recordTypeId, AttributionSource attributionSource) {
        finishDataDeliveryRead(Collections.singletonList(recordTypeId), attributionSource);
    }

    private void finishDataDeliveryRead(
            List<Integer> recordTypeIds, AttributionSource attributionSource) {
        Trace.traceBegin(TRACE_TAG_READ_SUBTASKS, TAG_READ.concat("FinishDataDeliveryRead"));

        try {
            for (Integer recordTypeId : recordTypeIds) {
                String permissionName =
                        HealthPermissions.getHealthReadPermission(
                                RecordTypePermissionCategoryMapper
                                        .getHealthPermissionCategoryForRecordType(recordTypeId));
                mPermissionManager.finishDataDelivery(permissionName, attributionSource);
            }
        } catch (Exception exception) {
            // Ignore: HC API has already fulfilled the result, ignore any exception we hit here
        }
        Trace.traceEnd(TRACE_TAG_READ_SUBTASKS);
    }

    private void finishDataDeliveryWriteRecords(
            List<RecordInternal<?>> recordInternals, AttributionSource attributionSource) {
        Trace.traceBegin(TRACE_TAG_READ_SUBTASKS, TAG_READ.concat(".FinishDataDeliveryWrite"));
        Set<Integer> recordTypeIdsToEnforce = new ArraySet<>();
        for (RecordInternal<?> recordInternal : recordInternals) {
            recordTypeIdsToEnforce.add(recordInternal.getRecordType());
        }

        finishDataDeliveryWrite(recordTypeIdsToEnforce.stream().toList(), attributionSource);
        Trace.traceEnd(TRACE_TAG_READ_SUBTASKS);
    }

    private void finishDataDeliveryWrite(
            List<Integer> recordTypeIds, AttributionSource attributionSource) {
        try {
            for (Integer recordTypeId : recordTypeIds) {
                String permissionName =
                        HealthPermissions.getHealthWritePermission(
                                RecordTypePermissionCategoryMapper
                                        .getHealthPermissionCategoryForRecordType(recordTypeId));
                mPermissionManager.finishDataDelivery(permissionName, attributionSource);
            }
        } catch (Exception exception) {
            // Ignore: HC API has already fulfilled the result, ignore any exception we hit here
        }
    }

    private void enforceBinderUidIsSameAsAttributionSourceUid(
            int binderUid, int attributionSourceUid) {
        if (binderUid != attributionSourceUid) {
            throw new SecurityException("Binder uid must be equal to attribution source uid.");
        }
    }

    private void throwExceptionIncorrectPermissionState() {
        throw new IllegalStateException(
                "Incorrect health permission state, likely"
                        + " because the calling application's manifest does not specify handling "
                        + Intent.ACTION_VIEW_PERMISSION_USAGE
                        + " with "
                        + HealthConnectManager.CATEGORY_HEALTH_PERMISSIONS);
    }

    private void logRecordTypeSpecificUpsertMetrics(
            @NonNull List<RecordInternal<?>> recordInternals, @NonNull String packageName) {
        Objects.requireNonNull(recordInternals);
        Objects.requireNonNull(packageName);

        Map<Integer, List<RecordInternal<?>>> recordTypeToRecordInternals =
                getRecordTypeToListOfRecords(recordInternals);
        for (Entry<Integer, List<RecordInternal<?>>> recordTypeToRecordInternalsEntry :
                recordTypeToRecordInternals.entrySet()) {
            RecordHelper<?> recordHelper =
                    RecordHelperProvider.getInstance()
                            .getRecordHelper(recordTypeToRecordInternalsEntry.getKey());
            recordHelper.logUpsertMetrics(recordTypeToRecordInternalsEntry.getValue(), packageName);
        }
    }

    private void logRecordTypeSpecificReadMetrics(
            @NonNull List<RecordInternal<?>> recordInternals, @NonNull String packageName) {
        Objects.requireNonNull(recordInternals);
        Objects.requireNonNull(packageName);

        Map<Integer, List<RecordInternal<?>>> recordTypeToRecordInternals =
                getRecordTypeToListOfRecords(recordInternals);
        for (Entry<Integer, List<RecordInternal<?>>> recordTypeToRecordInternalsEntry :
                recordTypeToRecordInternals.entrySet()) {
            RecordHelper<?> recordHelper =
                    RecordHelperProvider.getInstance()
                            .getRecordHelper(recordTypeToRecordInternalsEntry.getKey());
            recordHelper.logReadMetrics(recordTypeToRecordInternalsEntry.getValue(), packageName);
        }
    }

    private Map<Integer, List<RecordInternal<?>>> getRecordTypeToListOfRecords(
            List<RecordInternal<?>> recordInternals) {

        return recordInternals.stream()
                .collect(Collectors.groupingBy(RecordInternal::getRecordType));
    }

    private void throwSecurityException(String message) {
        throw new SecurityException(message);
    }

    private void throwExceptionIfDataSyncInProgress() {
        if (isDataSyncInProgress()) {
            throw new HealthConnectException(
                    HealthConnectException.ERROR_DATA_SYNC_IN_PROGRESS,
                    "Storage data sync in progress. API calls are blocked");
        }
    }

    /**
     * Throws an IllegalState Exception if data migration or restore is in process. This is only
     * used by HealthConnect synchronous APIs as {@link HealthConnectException} is lost between
     * processes on synchronous APIs and can only be returned to the caller for the APIs with a
     * callback.
     */
    private void throwIllegalStateExceptionIfDataSyncInProgress() {
        if (isDataSyncInProgress()) {
            throw new IllegalStateException("Storage data sync in progress. API calls are blocked");
        }
    }

    private static void postDeleteTasks(List<Integer> recordTypeIdsToDelete) {
        Trace.traceBegin(TRACE_TAG_DELETE_SUBTASKS, TAG_INSERT.concat("PostDeleteTasks"));
        if (recordTypeIdsToDelete != null && !recordTypeIdsToDelete.isEmpty()) {
            AppInfoHelper.getInstance()
                    .syncAppInfoRecordTypesUsed(new HashSet<>(recordTypeIdsToDelete));
            ActivityDateHelper.getInstance().reSyncByRecordTypeIds(recordTypeIdsToDelete);
        }
        Trace.traceEnd(TRACE_TAG_DELETE_SUBTASKS);
    }

    private static void tryAndReturnResult(
            IEmptyResponseCallback callback, HealthConnectServiceLogger.Builder builder) {
        try {
            callback.onResult();
            builder.setHealthDataServiceApiStatusSuccess();
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote call failed", e);
            builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
        }
    }

    private static void tryAndReturnResult(
            IInsertRecordsResponseCallback callback,
            List<String> uuids,
            HealthConnectServiceLogger.Builder builder) {
        try {
            callback.onResult(new InsertRecordsResponseParcel(uuids));
            builder.setHealthDataServiceApiStatusSuccess();
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote call failed", e);
            builder.setHealthDataServiceApiStatusError(ERROR_INTERNAL);
        }
    }

    private static void tryAndThrowException(
            @NonNull IInsertRecordsResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IAggregateRecordsResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IReadRecordsResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IActivityDatesResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IGetChangeLogTokenCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IAccessLogsResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IEmptyResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IApplicationInfoResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IChangeLogsResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IRecordTypeInfoResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IGetPriorityResponseCallback callback,
            @NonNull Exception exception,
            @HealthConnectException.ErrorCode int errorCode) {
        try {
            callback.onError(
                    new HealthConnectExceptionParcel(
                            new HealthConnectException(errorCode, exception.toString())));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }

    private static void tryAndThrowException(
            @NonNull IMigrationCallback callback,
            @NonNull Exception exception,
            @MigrationException.ErrorCode int errorCode,
            @Nullable String failedEntityId) {
        try {
            callback.onError(
                    new MigrationException(exception.toString(), errorCode, failedEntityId));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to send result to the callback", e);
        }
    }
}
