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

Commit bd4ae50c authored by Sergey Nikolaienkov's avatar Sergey Nikolaienkov Committed by Automerger Merge Worker
Browse files

Merge "Introduce run-cleanup adb command for CTS test" into tm-dev am: ea8aa9e3

parents 6c9bb47b ea8aa9e3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -7044,7 +7044,7 @@
                 android:permission="android.permission.BIND_JOB_SERVICE">
        </service>

        <service android:name="com.android.server.companion.AssociationCleanUpService"
        <service android:name="com.android.server.companion.InactiveAssociationsRemovalService"
                 android:permission="android.permission.BIND_JOB_SERVICE">
        </service>

+22 −16
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
@@ -121,8 +122,10 @@ public class CompanionDeviceManagerService extends SystemService {

    private static final String PREF_FILE_NAME = "companion_device_preferences.xml";
    private static final String PREF_KEY_AUTO_REVOKE_GRANTS_DONE = "auto_revoke_grants_done";
    private static final String SYS_PROP_DEBUG_REMOVAL_TIME_WINDOW =
            "debug.cdm.cdmservice.removal_time_window";

    private static final long ASSOCIATION_CLEAN_UP_TIME_WINDOW = DAYS.toMillis(3 * 30); // 3 months
    private static final long ASSOCIATION_REMOVAL_TIME_WINDOW_DEFAULT = DAYS.toMillis(90);

    private PersistentDataStore mPersistentStore;
    private final PersistUserStateHandler mUserPersistenceHandler;
@@ -211,8 +214,8 @@ public class CompanionDeviceManagerService extends SystemService {
            mPackageMonitor.register(context, FgThread.get().getLooper(), UserHandle.ALL, true);
            mDevicePresenceMonitor.init(context);
        } else if (phase == PHASE_BOOT_COMPLETED) {
            // Run the Association CleanUp job service daily.
            AssociationCleanUpService.schedule(getContext());
            // Run the Inactive Association Removal job service daily.
            InactiveAssociationsRemovalService.schedule(getContext());
        }
    }

@@ -410,17 +413,20 @@ public class CompanionDeviceManagerService extends SystemService {
        mCompanionAppController.onPackagesChanged(userId);
    }

    // Revoke associations if the selfManaged companion device does not connect for 3
    // months for specific profile.
    private void associationCleanUp(String profile) {
    // Revoke associations if the selfManaged companion device does not connect for 3 months.
    void removeInactiveSelfManagedAssociations() {
        final long currentTime = System.currentTimeMillis();
        long removalWindow = SystemProperties.getLong(SYS_PROP_DEBUG_REMOVAL_TIME_WINDOW, -1);
        if (removalWindow <= 0) {
            // 0 or negative values indicate that the sysprop was never set or should be ignored.
            removalWindow = ASSOCIATION_REMOVAL_TIME_WINDOW_DEFAULT;
        }

        for (AssociationInfo ai : mAssociationStore.getAssociations()) {
            if (ai.isSelfManaged()
                    && profile.equals(ai.getDeviceProfile())
                    && System.currentTimeMillis() - ai.getLastTimeConnectedMs()
                    >= ASSOCIATION_CLEAN_UP_TIME_WINDOW) {
                Slog.i(TAG, "Removing the association for associationId: "
                        + ai.getId()
                        + " due to the device does not connect for 3 months.");
            if (!ai.isSelfManaged()) continue;
            final boolean isInactive =  currentTime - ai.getLastTimeConnectedMs() >= removalWindow;
            if (isInactive) {
                Slog.i(TAG, "Removing inactive self-managed association: " + ai.getId());
                disassociateInternal(ai.getId());
            }
        }
@@ -1078,10 +1084,10 @@ public class CompanionDeviceManagerService extends SystemService {
        return ArrayUtils.contains(array, a) || ArrayUtils.contains(array, b);
    }

    private class LocalService extends CompanionDeviceManagerServiceInternal {
    private class LocalService implements CompanionDeviceManagerServiceInternal {
        @Override
        public void associationCleanUp(String profile) {
            CompanionDeviceManagerService.this.associationCleanUp(profile);
        public void removeInactiveSelfManagedAssociations() {
            CompanionDeviceManagerService.this.removeInactiveSelfManagedAssociations();
        }
    }

+3 −5
Original line number Diff line number Diff line
@@ -18,12 +18,10 @@ package com.android.server.companion;

/**
 * Companion Device Manager Local System Service Interface.
 *
 * @hide Only for use within the system server.
 */
public abstract class CompanionDeviceManagerServiceInternal {
interface CompanionDeviceManagerServiceInternal {
    /**
     * @see CompanionDeviceManagerService#associationCleanUp
     * @see CompanionDeviceManagerService#removeInactiveSelfManagedAssociations
     */
    public abstract void associationCleanUp(String profile);
    void removeInactiveSelfManagedAssociations();
}
+17 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.companion;

import android.companion.AssociationInfo;
import android.os.Binder;
import android.os.ShellCommand;
import android.util.Log;
import android.util.Slog;
@@ -96,6 +97,16 @@ class CompanionDeviceShellCommand extends ShellCommand {
                    mDevicePresenceMonitor.simulateDeviceDisappeared(associationId);
                    break;

                case "remove-inactive-associations": {
                    // This command should trigger the same "clean-up" job as performed by the
                    // InactiveAssociationsRemovalService JobService. However, since the
                    // InactiveAssociationsRemovalService run as system, we want to run this
                    // as system (not as shell/root) as well.
                    Binder.withCleanCallingIdentity(
                            mService::removeInactiveSelfManagedAssociations);
                }
                break;

                default:
                    return handleDefaultCommands(cmd);
            }
@@ -142,6 +153,12 @@ class CompanionDeviceShellCommand extends ShellCommand {
        pw.println("      invoked for the same device (same ASSOCIATION_ID) no longer than");
        pw.println("      60 seconds ago.");
        pw.println("      USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY.");

        pw.println("  remove-inactive-associations");
        pw.println("      Remove self-managed associations that have not been active ");
        pw.println("      for a long time (90 days or as configured via ");
        pw.println("      \"debug.cdm.cdmservice.cleanup_time_window\" system property). ");
        pw.println("      USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY.");
    }

    private int getNextIntArgRequired() {
+13 −16
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 * Copyright (C) 2022 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.
@@ -24,10 +24,8 @@ import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.companion.AssociationRequest;
import android.content.ComponentName;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Slog;

import com.android.server.LocalServices;
@@ -37,26 +35,24 @@ import com.android.server.LocalServices;
 * The job will be executed only if the device is charging and in idle mode due to the application
 * will be killed if association/role are revoked.
 */
public class AssociationCleanUpService extends JobService {
    private static final int JOB_ID = AssociationCleanUpService.class.hashCode();
public class InactiveAssociationsRemovalService extends JobService {
    private static final int JOB_ID = InactiveAssociationsRemovalService.class.hashCode();
    private static final long ONE_DAY_INTERVAL = DAYS.toMillis(1);

    @Override
    public boolean onStartJob(final JobParameters params) {
        Slog.i(TAG, "Execute the Association CleanUp job");
        // Special policy for APP_STREAMING role that need to revoke associations if the device
        // does not connect for 3 months.
        AsyncTask.execute(() -> {
        Slog.i(TAG, "Execute the Association Removal job");
        // Special policy for selfManaged that need to revoke associations if the device
        // does not connect for 90 days.
        LocalServices.getService(CompanionDeviceManagerServiceInternal.class)
                    .associationCleanUp(AssociationRequest.DEVICE_PROFILE_APP_STREAMING);
                .removeInactiveSelfManagedAssociations();
        jobFinished(params, false);
        });
        return true;
    }

    @Override
    public boolean onStopJob(final JobParameters params) {
        Slog.i(TAG, "Association cleanup job stopped; id=" + params.getJobId()
        Slog.i(TAG, "Association removal job stopped; id=" + params.getJobId()
                + ", reason="
                + JobParameters.getInternalReasonCodeDescription(
                params.getInternalStopReasonCode()));
@@ -64,10 +60,10 @@ public class AssociationCleanUpService extends JobService {
    }

    static void schedule(Context context) {
        Slog.i(TAG, "Scheduling the Association Cleanup job");
        Slog.i(TAG, "Scheduling the Association Removal job");
        final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
        final JobInfo job = new JobInfo.Builder(JOB_ID,
                new ComponentName(context, AssociationCleanUpService.class))
                new ComponentName(context, InactiveAssociationsRemovalService.class))
                .setRequiresCharging(true)
                .setRequiresDeviceIdle(true)
                .setPeriodic(ONE_DAY_INTERVAL)
@@ -75,3 +71,4 @@ public class AssociationCleanUpService extends JobService {
        jobScheduler.schedule(job);
    }
}