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

Commit 2c7f06e9 authored by Kuan Wang's avatar Kuan Wang
Browse files

Use taskRootPackageName instead of packageName to load uid when usage

resource is USAGE_SOURCE_TASK_ROOT_ACTIVITY and taskRootPackageName is
not empty.

This logic is consistent with digital wellbeing: assign the screen-on
time onto task root activity when usage resource is
USAGE_SOURCE_TASK_ROOT_ACTIVITY.

Bug: 260964679
Test: make RunSettingsRoboTests + manual
Change-Id: I4c7ed342d8c00951879f5826bf79575f330ce86e
parent a1a7cba6
Loading
Loading
Loading
Loading
+60 −8
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@ package com.android.settings.fuelgauge.batteryusage;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -25,7 +27,9 @@ import android.database.Cursor;
import android.os.BatteryUsageStats;
import android.os.Build;
import android.os.LocaleList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Base64;
import android.util.Log;
@@ -167,8 +171,10 @@ public final class ConvertUtils {
    /** Converts to {@link AppUsageEvent} from {@link Event} */
    @Nullable
    public static AppUsageEvent convertToAppUsageEvent(
            Context context, final Event event, final long userId) {
        if (event.getPackageName() == null) {
            Context context, final IUsageStatsManager usageStatsManager, final Event event,
            final long userId) {
        final String packageName = event.getPackageName();
        if (packageName == null) {
            // See b/190609174: Event package names should never be null, but sometimes they are.
            // Note that system events like device shutting down should still come with the android
            // package name.
@@ -182,13 +188,20 @@ public final class ConvertUtils {
        appUsageEventBuilder
                .setTimestamp(event.getTimeStamp())
                .setType(getAppUsageEventType(event.getEventType()))
                .setPackageName(event.getPackageName())
                .setPackageName(packageName)
                .setUserId(userId);

        final String taskRootPackageName = getTaskRootPackageName(event);
        if (taskRootPackageName != null) {
            appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
        }

        final String effectivePackageName =
                getEffectivePackageName(usageStatsManager, packageName, taskRootPackageName);
        try {
            final long uid = context
                    .getPackageManager()
                    .getPackageUidAsUser(event.getPackageName(), (int) userId);
                    .getPackageUidAsUser(effectivePackageName, (int) userId);
            appUsageEventBuilder.setUid(uid);
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, String.format(
@@ -201,10 +214,6 @@ public final class ConvertUtils {
        } catch (NoClassDefFoundError | NoSuchMethodError e) {
            Log.w(TAG, "UsageEvent instance ID API error");
        }
        String taskRootPackageName = getTaskRootPackageName(event);
        if (taskRootPackageName != null) {
            appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
        }

        return appUsageEventBuilder.build();
    }
@@ -267,6 +276,35 @@ public final class ConvertUtils {
                : Locale.getDefault();
    }

    /**
     * Returns the package name the app usage should be attributed to.
     *
     * <ul>
     *   <li>If {@link UsageStatsManager#getUsageSource()} returns {@link
     *       UsageStatsManager#USAGE_SOURCE_CURRENT_ACTIVITY}, this method will return packageName.
     *   <li>If {@link UsageStatsManager#getUsageSource()} returns {@link
     *       UsageStatsManager#USAGE_SOURCE_TASK_ROOT_ACTIVITY}, this method will return
     *       taskRootPackageName if it exists, or packageName otherwise.
     * </ul>
     */
    @VisibleForTesting
    static String getEffectivePackageName(
            final IUsageStatsManager usageStatsManager, final String packageName,
            final String taskRootPackageName) {
        int usageSource = getUsageSource(usageStatsManager);
        switch (usageSource) {
            case UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY:
                return !TextUtils.isEmpty(taskRootPackageName)
                        ? taskRootPackageName
                        : packageName;
            case UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY:
                return packageName;
            default:
                Log.e(TAG, "Unexpected usage source: " + usageSource);
                return packageName;
        }
    }

    /**
     * Returns the package name of the task root when this event was reported when {@code event} is
     * one of:
@@ -298,6 +336,20 @@ public final class ConvertUtils {
        }
    }

    /**
     * Returns what App Usage Observers will consider the source of usage for an activity.
     *
     * @see UsageStatsManager#getUsageSource()
     */
    private static int getUsageSource(final IUsageStatsManager usageStatsManager) {
        try {
            return usageStatsManager.getUsageSource();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to getUsageSource", e);
            return UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
        }
    }

    private static AppUsageEventType getAppUsageEventType(final int eventType) {
        switch (eventType) {
            case Event.ACTIVITY_RESUMED:
+2 −1
Original line number Diff line number Diff line
@@ -256,7 +256,8 @@ public final class DataProcessor {
                            break;
                        }
                        final AppUsageEvent appUsageEvent =
                                ConvertUtils.convertToAppUsageEvent(context, event, userId);
                                ConvertUtils.convertToAppUsageEvent(
                                        context, sUsageStatsManager, event, userId);
                        if (appUsageEvent != null) {
                            numEventsFetched++;
                            appUsageEventList.add(appUsageEvent);
+60 −4
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.settings.fuelgauge.batteryusage;

import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
@@ -22,6 +25,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.content.ContentValues;
@@ -31,6 +35,7 @@ import android.database.MatrixCursor;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.LocaleList;
import android.os.RemoteException;
import android.os.UserHandle;

import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
@@ -56,6 +61,8 @@ public final class ConvertUtilsTest {
    @Mock
    private BatteryUsageStats mBatteryUsageStats;
    @Mock
    private IUsageStatsManager mUsageStatsManager;
    @Mock
    private BatteryEntry mMockBatteryEntry;

    @Before
@@ -278,7 +285,7 @@ public final class ConvertUtilsTest {

        final long userId = 2;
        final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
                mContext, event, userId);
                mContext, mUsageStatsManager, event, userId);
        assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
        assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.ACTIVITY_RESUMED);
        assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
@@ -299,7 +306,7 @@ public final class ConvertUtilsTest {

        final long userId = 1;
        final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
                mContext, event, userId);
                mContext, mUsageStatsManager, event, userId);
        assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
        assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
        assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
@@ -315,7 +322,7 @@ public final class ConvertUtilsTest {
        event.mPackage = null;

        final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
                mContext, event, /*userId=*/ 0);
                mContext, mUsageStatsManager, event, /*userId=*/ 0);

        assertThat(appUsageEvent).isNull();
    }
@@ -331,7 +338,7 @@ public final class ConvertUtilsTest {

        final long userId = 1;
        final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
                mContext, event, userId);
                mContext, mUsageStatsManager, event, userId);

        assertThat(appUsageEvent).isNull();
    }
@@ -415,4 +422,53 @@ public final class ConvertUtilsTest {
        mContext.getResources().getConfiguration().setLocales(new LocaleList());
        assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
    }

    @Test
    public void getEffectivePackageName_currentActivity_returnPackageName() throws RemoteException {
        when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_CURRENT_ACTIVITY);
        final String packageName = "com.android.settings1";
        final String taskRootPackageName = "com.android.settings2";

        assertThat(ConvertUtils.getEffectivePackageName(
                mUsageStatsManager, packageName, taskRootPackageName))
                .isEqualTo(packageName);
    }

    @Test
    public void getEffectivePackageName_usageSourceThrowException_returnPackageName()
            throws RemoteException {
        when(mUsageStatsManager.getUsageSource()).thenThrow(new RemoteException());
        final String packageName = "com.android.settings1";
        final String taskRootPackageName = "com.android.settings2";

        assertThat(ConvertUtils.getEffectivePackageName(
                mUsageStatsManager, packageName, taskRootPackageName))
                .isEqualTo(packageName);
    }

    @Test
    public void getEffectivePackageName_rootActivity_returnTaskRootPackageName()
            throws RemoteException {
        when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
        final String packageName = "com.android.settings1";
        final String taskRootPackageName = "com.android.settings2";

        assertThat(ConvertUtils.getEffectivePackageName(
                mUsageStatsManager, packageName, taskRootPackageName))
                .isEqualTo(taskRootPackageName);
    }

    @Test
    public void getEffectivePackageName_nullOrEmptyTaskRoot_returnPackageName()
            throws RemoteException {
        when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
        final String packageName = "com.android.settings1";

        assertThat(ConvertUtils.getEffectivePackageName(
                mUsageStatsManager, packageName, /*taskRootPackageName=*/ null))
                .isEqualTo(packageName);
        assertThat(ConvertUtils.getEffectivePackageName(
                mUsageStatsManager, packageName, /*taskRootPackageName=*/ ""))
                .isEqualTo(packageName);
    }
}