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

Commit 53b4314a authored by Kang Li's avatar Kang Li
Browse files

Add Sharing Histories to UsageStatsManager.

This CL is for Android O Smart-Sharing (b/30982298). By this CL, sharing
counts are logged with UsageStatsManager.

Bug: 30982298
Test: manual - shared images in Camera and texts in Chrome using a mobile device.

Change-Id: I0b4aa0506f99b3083d140a48f7b4bdd5b1c5afb6
parent 2c0dc3e0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -34,4 +34,6 @@ interface IUsageStatsManager {
    boolean isAppInactive(String packageName, int userId);
    void whitelistAppTemporarily(String packageName, long duration, int userId);
    void onCarrierPrivilegedAppsChanged();
    void reportChooserSelection(String packageName, int userId, String contentType,
            in String[] annotations, String action);
}
+40 −0
Original line number Diff line number Diff line
@@ -85,6 +85,12 @@ public final class UsageEvents implements Parcelable {
         */
        public static final int SHORTCUT_INVOCATION = 8;

        /**
         * An event type denoting that a package was selected by the user for ChooserActivity.
         * @hide
         */
        public static final int CHOOSER_ACTION = 9;

        /**
         * {@hide}
         */
@@ -118,6 +124,27 @@ public final class UsageEvents implements Parcelable {
         */
        public String mShortcutId;

        /**
         * Action type passed to ChooserActivity
         * Only present for {@link #CHOOSER_ACTION} event types.
         * {@hide}
         */
        public String mAction;

        /**
         * Content type passed to ChooserActivity.
         * Only present for {@link #CHOOSER_ACTION} event types.
         * {@hide}
         */
        public String mContentType;

        /**
         * Content annotations passed to ChooserActivity.
         * Only present for {@link #CHOOSER_ACTION} event types.
         * {@hide}
         */
        public String[] mContentAnnotations;

        /**
         * The package name of the source of this event.
         */
@@ -307,6 +334,11 @@ public final class UsageEvents implements Parcelable {
            case Event.SHORTCUT_INVOCATION:
                p.writeString(event.mShortcutId);
                break;
            case Event.CHOOSER_ACTION:
                p.writeString(event.mAction);
                p.writeString(event.mContentType);
                p.writeStringArray(event.mContentAnnotations);
                break;
        }
    }

@@ -333,6 +365,9 @@ public final class UsageEvents implements Parcelable {
        // Fill out the event-dependant fields.
        eventOut.mConfiguration = null;
        eventOut.mShortcutId = null;
        eventOut.mAction = null;
        eventOut.mContentType = null;
        eventOut.mContentAnnotations = null;

        switch (eventOut.mEventType) {
            case Event.CONFIGURATION_CHANGE:
@@ -342,6 +377,11 @@ public final class UsageEvents implements Parcelable {
            case Event.SHORTCUT_INVOCATION:
                eventOut.mShortcutId = p.readString();
                break;
            case Event.CHOOSER_ACTION:
                eventOut.mAction = p.readString();
                eventOut.mContentType = p.readString();
                eventOut.mContentAnnotations = p.createStringArray();
                break;
        }
    }

+62 −0
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package android.app.usage;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;

/**
 * Contains usage statistics for an app package for a specific
@@ -61,6 +63,11 @@ public final class UsageStats implements Parcelable {
     */
    public int mLastEvent;

    /**
     * {@hide}
     */
    public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts;

    /**
     * {@hide}
     */
@@ -75,6 +82,7 @@ public final class UsageStats implements Parcelable {
        mTotalTimeInForeground = stats.mTotalTimeInForeground;
        mLaunchCount = stats.mLaunchCount;
        mLastEvent = stats.mLastEvent;
        mChooserCounts = stats.mChooserCounts;
    }

    public String getPackageName() {
@@ -142,6 +150,26 @@ public final class UsageStats implements Parcelable {
        mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
        mTotalTimeInForeground += right.mTotalTimeInForeground;
        mLaunchCount += right.mLaunchCount;
        if (mChooserCounts == null) {
            mChooserCounts = right.mChooserCounts;
        } else if (right.mChooserCounts != null) {
            final int chooserCountsSize = right.mChooserCounts.size();
            for (int i = 0; i < chooserCountsSize; i++) {
                String action = right.mChooserCounts.keyAt(i);
                ArrayMap<String, Integer> counts = right.mChooserCounts.valueAt(i);
                if (!mChooserCounts.containsKey(action) || mChooserCounts.get(action) == null) {
                    mChooserCounts.put(action, counts);
                    continue;
                }
                final int annotationSize = counts.size();
                for (int j = 0; j < annotationSize; j++) {
                    String key = counts.keyAt(j);
                    int rightValue = counts.valueAt(j);
                    int leftValue = mChooserCounts.get(action).getOrDefault(key, 0);
                    mChooserCounts.get(action).put(key, leftValue + rightValue);
                }
            }
        }
    }

    @Override
@@ -158,6 +186,21 @@ public final class UsageStats implements Parcelable {
        dest.writeLong(mTotalTimeInForeground);
        dest.writeInt(mLaunchCount);
        dest.writeInt(mLastEvent);
        Bundle allCounts = new Bundle();
        if (mChooserCounts != null) {
            final int chooserCountSize = mChooserCounts.size();
            for (int i = 0; i < chooserCountSize; i++) {
                String action = mChooserCounts.keyAt(i);
                ArrayMap<String, Integer> counts = mChooserCounts.valueAt(i);
                Bundle currentCounts = new Bundle();
                final int annotationSize = counts.size();
                for (int j = 0; j < annotationSize; j++) {
                    currentCounts.putInt(counts.keyAt(j), counts.valueAt(j));
                }
                allCounts.putBundle(action, currentCounts);
            }
        }
        dest.writeBundle(allCounts);
    }

    public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -171,6 +214,25 @@ public final class UsageStats implements Parcelable {
            stats.mTotalTimeInForeground = in.readLong();
            stats.mLaunchCount = in.readInt();
            stats.mLastEvent = in.readInt();
            Bundle allCounts = in.readBundle();
            if (allCounts != null) {
                stats.mChooserCounts = new ArrayMap<>();
                for (String action : allCounts.keySet()) {
                    if (!stats.mChooserCounts.containsKey(action)) {
                        ArrayMap<String, Integer> newCounts = new ArrayMap<>();
                        stats.mChooserCounts.put(action, newCounts);
                    }
                    Bundle currentCounts = allCounts.getBundle(action);
                    if (currentCounts != null) {
                        for (String key : currentCounts.keySet()) {
                            int value = currentCounts.getInt(key);
                            if (value > 0) {
                                stats.mChooserCounts.get(action).put(key, value);
                            }
                        }
                    }
                }
            }
            return stats;
        }

+19 −0
Original line number Diff line number Diff line
@@ -278,4 +278,23 @@ public final class UsageStatsManager {
        } catch (RemoteException re) {
        }
    }

    /**
     * Reports a Chooser action to the UsageStatsManager.
     *
     * @param packageName The package name of the app that is selected.
     * @param userId The user id of who makes the selection.
     * @param contentType The type of the content, e.g., Image, Video, App.
     * @param annotations The annotations of the content, e.g., Game, Selfie.
     * @param action The action type of Intent that invokes ChooserActivity.
     * {@link UsageEvents}
     * @hide
     */
    public void reportChooserSelection(String packageName, int userId, String contentType,
                                       String[] annotations, String action) {
        try {
            mService.reportChooserSelection(packageName, userId, contentType, annotations, action);
        } catch (RemoteException re) {
        }
    }
}
+32 −4
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.internal.app;
import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -398,6 +399,7 @@ public class ChooserActivity extends ResolverActivity {
                }
            }
        }
        updateChooserCounts(target, mContentType);
        return super.onTargetSelected(target, alwaysCheck);
    }

@@ -542,21 +544,47 @@ public class ChooserActivity extends ResolverActivity {
        // Do nothing. We'll send the voice stuff ourselves.
    }

    void updateChooserCounts(TargetInfo info, String annotation) {
        if (info != null) {
            UsageStatsManager usageStatsManager =
                    (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
            if (usageStatsManager == null) {
                if (DEBUG) {
                    Log.d(TAG, "Can not start UsageStatsManager");
                }
                return;
            }
            final ResolveInfo ri = info.getResolveInfo();
            if (ri != null && ri.activityInfo != null) {
                usageStatsManager.reportChooserSelection(ri.activityInfo.packageName, getUserId(),
                        annotation, null, info.getResolvedIntent().getAction());
                if (DEBUG) {
                    Log.d(TAG, "ResolveInfo Package is" + ri.activityInfo.packageName);
                }
            } else if(DEBUG) {
                Log.d(TAG, "Can not log Chooser Counts of null ResovleInfo");
            }
        }
    }

    void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
        if (mRefinementResultReceiver != null) {
            mRefinementResultReceiver.destroy();
            mRefinementResultReceiver = null;
        }

        if (selectedTarget == null) {
            Log.e(TAG, "Refinement result intent did not match any known targets; canceling");
        } else if (!checkTargetSourceIntent(selectedTarget, matchingIntent)) {
            Log.e(TAG, "onRefinementResult: Selected target " + selectedTarget
                    + " cannot match refined source intent " + matchingIntent);
        } else if (super.onTargetSelected(selectedTarget.cloneFilledIn(matchingIntent, 0), false)) {
        } else {
            TargetInfo clonedTarget = selectedTarget.cloneFilledIn(matchingIntent, 0);
            if (super.onTargetSelected(clonedTarget, false)) {
                updateChooserCounts(clonedTarget, mContentType);
                finish();
                return;
            }
        }
        onRefinementCanceled();
    }

Loading