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

Commit e39ca6e2 authored by Kevin Han's avatar Kevin Han
Browse files

Send boot complete broadcast when unhibernated

Apps that have been force-stopped may want to register job/alarms when
they are no longer force-stopped, so resend the boot complete broadcast
when an app is unhibernated.

Bug: 185261245
Test: atest AppHibernationServiceTest
Test: manual
Change-Id: Ia60f7b566d2f03746b232e0ea5a8002d33703f09
parent 9856c295
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.apphibernation;

import static android.app.AppOpsManager.OP_NONE;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static android.content.Intent.EXTRA_REMOVED_FOR_ALL_USERS;
@@ -25,8 +26,10 @@ import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;

import static com.android.server.apphibernation.AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
@@ -366,6 +369,49 @@ public final class AppHibernationService extends SystemService {
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
        pkgState.hibernated = false;
        pkgState.lastUnhibernatedMs = System.currentTimeMillis();
        // Deliver LOCKED_BOOT_COMPLETE AND BOOT_COMPLETE broadcast so app can re-register
        // their alarms/jobs/etc.
        try {
            Intent lockedBcIntent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)
                    .setPackage(packageName);
            final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED};
            mIActivityManager.broadcastIntentWithFeature(
                    null /* caller */,
                    null /* callingFeatureId */,
                    lockedBcIntent,
                    null /* resolvedType */,
                    null /* resultTo */,
                    Activity.RESULT_OK,
                    null /* resultData */,
                    null /* resultExtras */,
                    requiredPermissions,
                    null /* excludedPermissions */,
                    OP_NONE,
                    null /* bOptions */,
                    false /* serialized */,
                    false /* sticky */,
                    userId);

            Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED).setPackage(packageName);
            mIActivityManager.broadcastIntentWithFeature(
                    null /* caller */,
                    null /* callingFeatureId */,
                    bcIntent,
                    null /* resolvedType */,
                    null /* resultTo */,
                    Activity.RESULT_OK,
                    null /* resultData */,
                    null /* resultExtras */,
                    requiredPermissions,
                    null /* excludedPermissions */,
                    OP_NONE,
                    null /* bOptions */,
                    false /* serialized */,
                    false /* sticky */,
                    userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }

+20 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static org.mockito.ArgumentMatchers.intThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.app.IActivityManager;
@@ -264,6 +265,25 @@ public final class AppHibernationServiceTest {
        assertFalse(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1));
    }

    @Test
    public void testUnhibernatingPackageForUserSendsBootCompleteBroadcast()
            throws RemoteException {
        // GIVEN a hibernating package for a user
        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);

        // WHEN we unhibernate the package
        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, false);

        // THEN we send the boot complete broadcasts
        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mIActivityManager, times(2)).broadcastIntentWithFeature(any(), any(),
                intentArgumentCaptor.capture(), any(), any(), anyInt(), any(), any(), any(), any(),
                anyInt(), any(), anyBoolean(), anyBoolean(), eq(USER_ID_1));
        List<Intent> capturedIntents = intentArgumentCaptor.getAllValues();
        assertEquals(capturedIntents.get(0).getAction(), Intent.ACTION_LOCKED_BOOT_COMPLETED);
        assertEquals(capturedIntents.get(1).getAction(), Intent.ACTION_BOOT_COMPLETED);
    }

    /**
     * Add a mock user with one package.
     */