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

Commit 36391620 authored by Susi Kharraz-Post's avatar Susi Kharraz-Post Committed by Automerger Merge Worker
Browse files

Merge "Add sharesheet statsd logging" into rvc-dev am: f9617e33

Change-Id: Idc38d72a92c09029a3390d6cef5550249432795f
parents bb1af287 f9617e33
Loading
Loading
Loading
Loading
+65 −5
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.GridLayoutManager;
import com.android.internal.widget.RecyclerView;
import com.android.internal.widget.ResolverDrawerLayout;
@@ -178,7 +179,7 @@ public class ChooserActivity extends ResolverActivity implements
    private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = true;
    // TODO(b/123088566) Share these in a better way.
    private static final String APP_PREDICTION_SHARE_UI_SURFACE = "share";
    public static final String LAUNCH_LOCATON_DIRECT_SHARE = "direct_share";
    public static final String LAUNCH_LOCATION_DIRECT_SHARE = "direct_share";
    private static final int APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
    public static final String APP_PREDICTION_INTENT_FILTER_KEY = "intent_filter";

@@ -194,6 +195,14 @@ public class ChooserActivity extends ResolverActivity implements
    public static final int TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER = 2;
    public static final int TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE = 3;

    public static final int SELECTION_TYPE_SERVICE = 1;
    public static final int SELECTION_TYPE_APP = 2;
    public static final int SELECTION_TYPE_STANDARD = 3;
    public static final int SELECTION_TYPE_COPY = 4;

    // statsd logger wrapper
    protected ChooserActivityLogger mChooserActivityLogger;

    private static final boolean USE_CHOOSER_TARGET_SERVICE_FOR_DIRECT_TARGETS = true;

    @IntDef(flag = false, prefix = { "TARGET_TYPE_" }, value = {
@@ -270,9 +279,9 @@ public class ChooserActivity extends ResolverActivity implements

    // Starting at 1 since 0 is considered "undefined" for some of the database transformations
    // of tron logs.
    private static final int CONTENT_PREVIEW_IMAGE = 1;
    private static final int CONTENT_PREVIEW_FILE = 2;
    private static final int CONTENT_PREVIEW_TEXT = 3;
    protected static final int CONTENT_PREVIEW_IMAGE = 1;
    protected static final int CONTENT_PREVIEW_FILE = 2;
    protected static final int CONTENT_PREVIEW_TEXT = 3;
    protected MetricsLogger mMetricsLogger;

    private ContentPreviewCoordinator mPreviewCoord;
@@ -500,6 +509,9 @@ public class ChooserActivity extends ResolverActivity implements

                case CHOOSER_TARGET_SERVICE_WATCHDOG_MAX_TIMEOUT:
                    mMinTimeoutPassed = true;
                    if (!mServiceConnections.isEmpty()) {
                        getChooserActivityLogger().logSharesheetDirectLoadTimeout();
                    }
                    unbindRemainingServices();
                    maybeStopServiceRequestTimer();
                    break;
@@ -533,6 +545,7 @@ public class ChooserActivity extends ResolverActivity implements
                    logDirectShareTargetReceived(
                            MetricsEvent.ACTION_DIRECT_SHARE_TARGETS_LOADED_SHORTCUT_MANAGER);
                    sendVoiceChoicesIfNeeded();
                    getChooserActivityLogger().logSharesheetDirectLoadComplete();
                    break;

                default:
@@ -544,6 +557,7 @@ public class ChooserActivity extends ResolverActivity implements
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        final long intentReceivedTime = System.currentTimeMillis();
        getChooserActivityLogger().logSharesheetTriggered();
        // This is the only place this value is being set. Effectively final.
        mIsAppPredictorComponentAvailable = isAppPredictionServiceAvailable();

@@ -707,6 +721,8 @@ public class ChooserActivity extends ResolverActivity implements
                                incrementNumSheetExpansions();
                                mWrittenOnce = true;
                            }
                            getChooserActivityLogger()
                                    .logSharesheetExpansionChanged(isCollapsed);
                        }
                    });
        }
@@ -715,6 +731,16 @@ public class ChooserActivity extends ResolverActivity implements
            Log.d(TAG, "System Time Cost is " + systemCost);
        }

        getChooserActivityLogger().logShareStarted(
                FrameworkStatsLog.SHARESHEET_STARTED,
                getReferrerPackageName(),
                target.getType(),
                initialIntents == null ? 0 : initialIntents.length,
                mCallerChooserTargets == null ? 0 : mCallerChooserTargets.length,
                isWorkProfile(),
                findPreferredContentPreview(getTargetIntent(), getContentResolver()),
                target.getAction()
        );
        mDirectShareShortcutInfoCache = new HashMap<>();
    }

@@ -969,6 +995,10 @@ public class ChooserActivity extends ResolverActivity implements
            LogMaker targetLogMaker = new LogMaker(
                    MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET).setSubtype(1);
            getMetricsLogger().write(targetLogMaker);
            getChooserActivityLogger().logShareTargetSelected(
                    SELECTION_TYPE_COPY,
                    "",
                    -1);

            finish();
        }
@@ -1644,18 +1674,33 @@ public class ChooserActivity extends ResolverActivity implements
                    if (mCallerChooserTargets != null) {
                        numCallerProvided = mCallerChooserTargets.length;
                    }
                    getChooserActivityLogger().logShareTargetSelected(
                            SELECTION_TYPE_SERVICE,
                            targetInfo.getResolveInfo().activityInfo.processName,
                            value
                    );
                    break;
                case ChooserListAdapter.TARGET_CALLER:
                case ChooserListAdapter.TARGET_STANDARD:
                    cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
                    value -= currentListAdapter.getSelectableServiceTargetCount();
                    numCallerProvided = currentListAdapter.getCallerTargetCount();
                    getChooserActivityLogger().logShareTargetSelected(
                            SELECTION_TYPE_APP,
                            targetInfo.getResolveInfo().activityInfo.processName,
                            value
                    );
                    break;
                case ChooserListAdapter.TARGET_STANDARD_AZ:
                    // A-Z targets are unranked standard targets; we use -1 to mark that they
                    // are from the alphabetical pool.
                    value = -1;
                    cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
                    getChooserActivityLogger().logShareTargetSelected(
                            SELECTION_TYPE_STANDARD,
                            targetInfo.getResolveInfo().activityInfo.processName,
                            value
                    );
                    break;
            }

@@ -2131,7 +2176,7 @@ public class ChooserActivity extends ResolverActivity implements
        if (appTarget != null) {
            directShareAppPredictor.notifyAppTargetEvent(
                    new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
                        .setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
                        .setLaunchLocation(LAUNCH_LOCATION_DIRECT_SHARE)
                        .build());
        }
    }
@@ -2290,6 +2335,13 @@ public class ChooserActivity extends ResolverActivity implements
        return mMetricsLogger;
    }

    protected ChooserActivityLogger getChooserActivityLogger() {
        if (mChooserActivityLogger == null) {
            mChooserActivityLogger = new ChooserActivityLoggerImpl();
        }
        return mChooserActivityLogger;
    }

    public class ChooserListController extends ResolverListController {
        public ChooserListController(Context context,
                PackageManager pm,
@@ -2601,6 +2653,7 @@ public class ChooserActivity extends ResolverActivity implements

        // don't support direct share on low ram devices
        if (ActivityManager.isLowRamDeviceStatic()) {
            getChooserActivityLogger().logSharesheetAppLoadComplete();
            return;
        }

@@ -2619,6 +2672,8 @@ public class ChooserActivity extends ResolverActivity implements

            queryTargetServices(chooserListAdapter);
        }

        getChooserActivityLogger().logSharesheetAppLoadComplete();
    }

    private void setupScrollListener() {
@@ -3777,4 +3832,9 @@ public class ChooserActivity extends ResolverActivity implements
            canvas.drawRoundRect(x, y, width, height, mRadius, mRadius, mRoundRectPaint);
        }
    }

    @Override
    protected void maybeLogProfileChange() {
        getChooserActivityLogger().logShareheetProfileChanged();
    }
}
+215 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.internal.app;

import android.content.Intent;
import android.provider.MediaStore;

import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.FrameworkStatsLog;

/**
 * Interface for writing Sharesheet atoms to statsd log.
 * @hide
 */
public interface ChooserActivityLogger {
    /** Logs a UiEventReported event for the system sharesheet completing initial start-up. */
    void logShareStarted(int eventId, String packageName, String mimeType, int appProvidedDirect,
            int appProvidedApp, boolean isWorkprofile, int previewType, String intent);

    /** Logs a UiEventReported event for the system sharesheet when the user selects a target. */
    void logShareTargetSelected(int targetType, String packageName, int positionPicked);

    /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */
    default void logSharesheetTriggered() {
        log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, getInstanceId());
    }

    /** Logs a UiEventReported event for the system sharesheet completing loading app targets. */
    default void logSharesheetAppLoadComplete() {
        log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, getInstanceId());
    }

    /**
     * Logs a UiEventReported event for the system sharesheet completing loading service targets.
     */
    default void logSharesheetDirectLoadComplete() {
        log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, getInstanceId());
    }

    /**
     * Logs a UiEventReported event for the system sharesheet timing out loading service targets.
     */
    default void logSharesheetDirectLoadTimeout() {
        log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, getInstanceId());
    }

    /**
     * Logs a UiEventReported event for the system sharesheet switching
     * between work and main profile.
     */
    default void logShareheetProfileChanged() {
        log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, getInstanceId());
    }

    /** Logs a UiEventReported event for the system sharesheet getting expanded or collapsed. */
    default void logSharesheetExpansionChanged(boolean isCollapsed) {
        log(isCollapsed ? SharesheetStandardEvent.SHARESHEET_COLLAPSED :
                SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId());
    }

    /**
     * Logs a UiEventReported event for a given share activity
     * @param event
     * @param instanceId
     */
    void log(UiEventLogger.UiEventEnum event, InstanceId instanceId);

    /**
     *
     * @return
     */
    InstanceId getInstanceId();

    /**
     * The UiEvent enums that this class can log.
     */
    enum SharesheetStartedEvent implements UiEventLogger.UiEventEnum {
        @UiEvent(doc = "Basic system Sharesheet has started and is visible.")
        SHARE_STARTED(228);

        private final int mId;
        SharesheetStartedEvent(int id) {
            mId = id;
        }
        @Override
        public int getId() {
            return mId;
        }
    }

    /**
     * The UiEvent enums that this class can log.
     */
    enum SharesheetTargetSelectedEvent implements UiEventLogger.UiEventEnum {
        INVALID(0),
        @UiEvent(doc = "User selected a service target.")
        SHARESHEET_SERVICE_TARGET_SELECTED(232),
        @UiEvent(doc = "User selected an app target.")
        SHARESHEET_APP_TARGET_SELECTED(233),
        @UiEvent(doc = "User selected a standard target.")
        SHARESHEET_STANDARD_TARGET_SELECTED(234),
        @UiEvent(doc = "User selected the copy target.")
        SHARESHEET_COPY_TARGET_SELECTED(235);

        private final int mId;
        SharesheetTargetSelectedEvent(int id) {
            mId = id;
        }
        @Override public int getId() {
            return mId;
        }

        public static SharesheetTargetSelectedEvent fromTargetType(int targetType) {
            switch(targetType) {
                case ChooserActivity.SELECTION_TYPE_SERVICE:
                    return SHARESHEET_SERVICE_TARGET_SELECTED;
                case ChooserActivity.SELECTION_TYPE_APP:
                    return SHARESHEET_APP_TARGET_SELECTED;
                case ChooserActivity.SELECTION_TYPE_STANDARD:
                    return SHARESHEET_STANDARD_TARGET_SELECTED;
                case ChooserActivity.SELECTION_TYPE_COPY:
                    return SHARESHEET_COPY_TARGET_SELECTED;
                default:
                    return INVALID;
            }
        }
    }

    /**
     * The UiEvent enums that this class can log.
     */
    enum SharesheetStandardEvent implements UiEventLogger.UiEventEnum {
        INVALID(0),
        @UiEvent(doc = "User clicked share.")
        SHARESHEET_TRIGGERED(227),
        @UiEvent(doc = "User changed from work to personal profile or vice versa.")
        SHARESHEET_PROFILE_CHANGED(229),
        @UiEvent(doc = "User expanded target list.")
        SHARESHEET_EXPANDED(230),
        @UiEvent(doc = "User collapsed target list.")
        SHARESHEET_COLLAPSED(231),
        @UiEvent(doc = "Sharesheet app targets is fully populated.")
        SHARESHEET_APP_LOAD_COMPLETE(322),
        @UiEvent(doc = "Sharesheet direct targets is fully populated.")
        SHARESHEET_DIRECT_LOAD_COMPLETE(323),
        @UiEvent(doc = "Sharesheet direct targets timed out.")
        SHARESHEET_DIRECT_LOAD_TIMEOUT(324);

        private final int mId;
        SharesheetStandardEvent(int id) {
            mId = id;
        }
        @Override public int getId() {
            return mId;
        }
    }

    /**
     * Returns the enum used in sharesheet started atom to indicate what preview type was used.
     */
    default int typeFromPreviewInt(int previewType) {
        switch(previewType) {
            case ChooserActivity.CONTENT_PREVIEW_IMAGE:
                return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_IMAGE;
            case ChooserActivity.CONTENT_PREVIEW_FILE:
                return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_FILE;
            case ChooserActivity.CONTENT_PREVIEW_TEXT:
            default:
                return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_TEXT;
        }
    }

    /**
     * Returns the enum used in sharesheet started atom to indicate what intent triggers the
     * ChooserActivity.
     */
    default int typeFromIntentString(String intent) {
        switch (intent) {
            case Intent.ACTION_VIEW:
                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_VIEW;
            case Intent.ACTION_EDIT:
                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_EDIT;
            case Intent.ACTION_SEND:
                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND;
            case Intent.ACTION_SENDTO:
                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SENDTO;
            case Intent.ACTION_SEND_MULTIPLE:
                return FrameworkStatsLog
                        .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND_MULTIPLE;
            case MediaStore.ACTION_IMAGE_CAPTURE:
                return FrameworkStatsLog
                        .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_IMAGE_CAPTURE;
            case Intent.ACTION_MAIN:
                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_MAIN;
            default:
                return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT;
        }
    }
}
+82 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.internal.app;

import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.util.FrameworkStatsLog;

/**
 * Standard implementation of ChooserActivityLogger interface.
 * @hide
 */
public class ChooserActivityLoggerImpl implements ChooserActivityLogger {
    private static final int SHARESHEET_INSTANCE_ID_MAX = (1 << 13);

    private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
    // A small per-notification ID, used for statsd logging.
    private InstanceId mInstanceId;
    private static InstanceIdSequence sInstanceIdSequence;

    @Override
    public void logShareStarted(int eventId, String packageName, String mimeType,
            int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType,
            String intent) {
        FrameworkStatsLog.write(FrameworkStatsLog.SHARESHEET_STARTED,
                /* event_id = 1 */ SharesheetStartedEvent.SHARE_STARTED.getId(),
                /* package_name = 2 */ packageName,
                /* instance_id = 3 */ getInstanceId().getId(),
                /* mime_type = 4 */ mimeType,
                /* num_app_provided_direct_targets = 5 */ appProvidedDirect,
                /* num_app_provided_app_targets = 6 */ appProvidedApp,
                /* is_workprofile = 7 */ isWorkprofile,
                /* previewType = 8 */ typeFromPreviewInt(previewType),
                /* intentType = 9 */ typeFromIntentString(intent));
    }

    @Override
    public void logShareTargetSelected(int targetType, String packageName, int positionPicked) {
        FrameworkStatsLog.write(FrameworkStatsLog.RANKING_SELECTED,
                /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(),
                /* package_name = 2 */ packageName,
                /* instance_id = 3 */ getInstanceId().getId(),
                /* position_picked = 4 */ positionPicked);
    }

    @Override
    public void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) {
        mUiEventLogger.logWithInstanceId(
                event,
                0,
                null,
                instanceId);
    }

    @Override
    public InstanceId getInstanceId() {
        if (mInstanceId == null) {
            if (sInstanceIdSequence == null) {
                sInstanceIdSequence = new InstanceIdSequence(SHARESHEET_INSTANCE_ID_MAX);
            }
            mInstanceId = sInstanceIdSequence.newInstanceId();
        }
        return mInstanceId;
    }

}
+3 −0
Original line number Diff line number Diff line
@@ -1578,6 +1578,7 @@ public class ResolverActivity extends Activity implements
                viewPager.setCurrentItem(1);
            }
            setupViewVisibilities();
            maybeLogProfileChange();
            DevicePolicyEventLogger
                    .createEvent(DevicePolicyEnums.RESOLVER_SWITCH_TABS)
                    .setInt(viewPager.getCurrentItem())
@@ -1998,4 +1999,6 @@ public class ResolverActivity extends Activity implements
            }
        }
    }

    protected void maybeLogProfileChange() {}
}
+1 −1
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ public class UiEventLoggerFake implements UiEventLogger {
    }

    @Override
    public void logWithInstanceId(UiEventLogger.UiEventEnum event, int uid, String packageName,
    public void logWithInstanceId(UiEventEnum event, int uid, String packageName,
            InstanceId instance) {
        final int eventId = event.getId();
        if (eventId > 0) {
Loading