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

Commit 5830a223 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6601700 from efdc4e23 to rvc-release

Change-Id: I92441f3520edae11e2a5f1a95ecbd940243b1faa
parents 9595878f efdc4e23
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ message ContainerInfo {
    ShortcutsContainer shortcuts_container = 8;
    SettingsContainer settings_container = 9;
    PredictedHotseatContainer predicted_hotseat_container = 10;
    TaskSwitcherContainer task_switcher_container = 11;
  }
}

@@ -82,6 +83,9 @@ message ShortcutsContainer {
message SettingsContainer {
}

message TaskSwitcherContainer {
}

enum Attribute {
  UNKNOWN = 0;
  DEFAULT_LAYOUT = 1;       // icon automatically placed in workspace, folder, hotseat
+40 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.launcher3.appprediction;

import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALL_APPS_RANKED;

import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
@@ -37,6 +38,8 @@ import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.shortcuts.ShortcutKey;
@@ -48,6 +51,7 @@ import com.android.launcher3.util.MainThreadInitializedObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.OptionalInt;
import java.util.stream.IntStream;

/**
@@ -301,6 +305,41 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
        return mCurrentState;
    }

    /**
     * Logs ranking info for launched app within all apps prediction.
     * Only applicable when {@link ItemInfo#itemType} is one of the followings:
     * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
     * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
     * {@link LauncherSettings.Favorites#ITEM_TYPE_DEEP_SHORTCUT}
     */
    public void logLaunchedAppRankingInfo(@NonNull ItemInfo itemInfo, InstanceId instanceId) {
        if (itemInfo.getTargetComponent() == null || itemInfo.user == null
                || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
                && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
                && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)) {
            return;
        }

        Launcher launcher = Launcher.getLauncher(mAppsView.getContext());
        final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
        final List<ComponentKeyMapper> predictedApps = getCurrentState().apps;
        OptionalInt rank = IntStream.range(0, predictedApps.size())
                .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
                .findFirst();
        if (!rank.isPresent()) {
            return;
        }

        LauncherAtom.ItemInfo.Builder atomBuilder = LauncherAtom.ItemInfo.newBuilder();
        atomBuilder.setRank(rank.getAsInt());
        atomBuilder.setContainerInfo(
                LauncherAtom.ContainerInfo.newBuilder().setPredictionContainer(
                        LauncherAtom.PredictionContainer.newBuilder().build()).build());
        launcher.getStatsLogManager().log(LAUNCHER_ALL_APPS_RANKED, instanceId,
                atomBuilder.build());
    }


    /**
     * Fill in predicted_rank field based on app prediction.
     * Only applicable when {@link ItemInfo#itemType} is one of the followings:
@@ -310,6 +349,7 @@ public class PredictionUiStateManager implements StateListener<LauncherState>,
     */
    public static void fillInPredictedRank(
            @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {

        final PredictionUiStateManager manager = PredictionUiStateManager.INSTANCE.getNoCreate();
        if (manager == null || itemInfo.getTargetComponent() == null || itemInfo.user == null
                || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+15 −14
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.launcher3.hybridhotseat;

import static com.android.launcher3.logging.StatsLogManager.LauncherEvent
        .LAUNCHER_HOTSEAT_EDU_ONLY_TIP;

import android.content.Intent;
import android.view.View;

@@ -47,12 +50,12 @@ public class HotseatEduController {
    public static final String KEY_HOTSEAT_EDU_SEEN = "hotseat_edu_seen";
    public static final String HOTSEAT_EDU_ACTION =
            "com.android.launcher3.action.SHOW_HYBRID_HOTSEAT_EDU";
    private static final String SETTINGS_ACTION =
    public static final String SETTINGS_ACTION =
            "android.settings.ACTION_CONTENT_SUGGESTIONS_SETTINGS";

    private final Launcher mLauncher;
    private final Hotseat mHotseat;
    private final HotseatRestoreHelper mRestoreHelper;
    private HotseatRestoreHelper mRestoreHelper;
    private List<WorkspaceItemInfo> mPredictedApps;
    private HotseatEduDialog mActiveDialog;

@@ -71,14 +74,17 @@ public class HotseatEduController {
     * Checks what type of migration should be used and migrates hotseat
     */
    void migrate() {
        if (mRestoreHelper != null) {
            mRestoreHelper.createBackup();
        }
        if (FeatureFlags.HOTSEAT_MIGRATE_TO_FOLDER.get()) {
            migrateToFolder();
        } else {
            migrateHotseatWhole();
        }
        Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_enabled, R.string.hotseat_turn_off,
                null, () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION)));
        Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_enabled,
                R.string.hotseat_prediction_settings, null,
                () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION)));
    }

    /**
@@ -223,15 +229,15 @@ public class HotseatEduController {

    void finishOnboarding() {
        mOnOnboardingComplete.run();
        destroy();
        mLauncher.getSharedPrefs().edit().putBoolean(KEY_HOTSEAT_EDU_SEEN, true).apply();
    }

    void showDimissTip() {
        if (mHotseat.getShortcutsAndWidgets().getChildCount()
                < mLauncher.getDeviceProfile().inv.numHotseatIcons) {
            Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled, R.string.hotseat_turn_off,
                    null, () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION)));
            Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled,
                    R.string.hotseat_prediction_settings, null,
                    () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION)));
        } else {
            new ArrowTipView(mLauncher).show(
                    mLauncher.getString(R.string.hotseat_tip_no_empty_slots), mHotseat.getTop());
@@ -242,12 +248,6 @@ public class HotseatEduController {
        mPredictedApps = predictedApps;
    }

    void destroy() {
        if (mActiveDialog != null) {
            mActiveDialog.setHotseatEduController(null);
        }
    }

    void showEdu() {
        int childCount = mHotseat.getShortcutsAndWidgets().getChildCount();
        CellLayout cellLayout = mLauncher.getWorkspace().getScreenWithId(Workspace.FIRST_SCREEN_ID);
@@ -265,6 +265,7 @@ public class HotseatEduController {
                    requiresMigration ? R.string.hotseat_tip_no_empty_slots
                            : R.string.hotseat_auto_enrolled),
                    mHotseat.getTop());
            mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_ONLY_TIP);
            finishOnboarding();
        }
    }
+9 −43
Original line number Diff line number Diff line
@@ -15,9 +15,10 @@
 */
package com.android.launcher3.hybridhotseat;

import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType
        .HYBRID_HOTSEAT_CANCELED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent
        .LAUNCHER_HOTSEAT_EDU_ACCEPT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_EDU_DENY;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_EDU_SEEN;

import android.animation.PropertyValuesHolder;
import android.content.Context;
@@ -29,15 +30,14 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.PredictedAppIcon;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -111,15 +111,13 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable

        mHotseatEduController.moveHotseatItems();
        mHotseatEduController.finishOnboarding();
        //TODO: pass actual page index here.
        // Temporarily we're passing 1 for folder migration and 2 for page migration
        logUserAction(true, FeatureFlags.HOTSEAT_MIGRATE_TO_FOLDER.get() ? 1 : 2);
        mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_ACCEPT);
    }

    private void onDismiss(View v) {
        mHotseatEduController.showDimissTip();
        mHotseatEduController.finishOnboarding();
        logUserAction(false, -1);
        mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_DENY);
        handleClose(true);
    }

@@ -163,39 +161,6 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable
        }
    }

    private void logUserAction(boolean migrated, int pageIndex) {
        LauncherLogProto.Action action = new LauncherLogProto.Action();
        LauncherLogProto.Target target = new LauncherLogProto.Target();

        int hotseatItemsCount = mLauncher.getHotseat().getShortcutsAndWidgets().getChildCount();
        // -1 to exclude smart space
        int workspaceItemCount = mLauncher.getWorkspace().getScreenWithId(
                Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets().getChildCount() - 1;

        action.type = LauncherLogProto.Action.Type.TOUCH;
        action.touch = LauncherLogProto.Action.Touch.TAP;
        target.containerType = LauncherLogProto.ContainerType.TIP;
        target.tipType = LauncherLogProto.TipType.HYBRID_HOTSEAT;
        target.controlType = migrated ? LauncherLogProto.ControlType.HYBRID_HOTSEAT_ACCEPTED
                : HYBRID_HOTSEAT_CANCELED;
        target.rank = MIGRATION_EXPERIMENT_IDENTIFIER;
        // encoding migration type on pageIndex
        target.pageIndex = pageIndex;
        target.cardinality = (workspaceItemCount * 1000) + hotseatItemsCount;
        LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
        UserEventDispatcher.newInstance(getContext()).dispatchUserEvent(event, null);
    }

    private void logOnBoardingSeen() {
        LauncherLogProto.Action action = new LauncherLogProto.Action();
        LauncherLogProto.Target target = new LauncherLogProto.Target();
        action.type = LauncherLogProto.Action.Type.TIP;
        target.containerType = LauncherLogProto.ContainerType.TIP;
        target.tipType = LauncherLogProto.TipType.HYBRID_HOTSEAT;
        LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
        UserEventDispatcher.newInstance(getContext()).dispatchUserEvent(event, null);
    }

    private void animateOpen() {
        if (mIsOpen || mOpenCloseAnimator.isRunning()) {
            return;
@@ -244,8 +209,9 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable
                || mHotseatEduController == null) {
            return;
        }
        AbstractFloatingView.closeAllOpenViews(mLauncher);
        attachToContainer();
        logOnBoardingSeen();
        mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_EDU_SEEN);
        animateOpen();
        populatePreview(predictions);
    }
+129 −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.launcher3.hybridhotseat;

import android.content.Context;
import android.os.Handler;
import android.util.Log;

import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.MainThreadInitializedObject;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Helper class to allow hot seat file logging
 */
public class HotseatFileLog {

    public static final int LOG_DAYS = 10;
    private static final String FILE_NAME_PREFIX = "hotseat-log-";
    private static final DateFormat DATE_FORMAT =
            DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
    public static final MainThreadInitializedObject<HotseatFileLog> INSTANCE =
            new MainThreadInitializedObject<>(HotseatFileLog::new);


    private final Handler mHandler = new Handler(
            Executors.createAndStartNewLooper("hotseat-logger"));
    private final File mLogsDir;
    private PrintWriter mCurrentWriter;
    private String mFileName;

    private HotseatFileLog(Context context) {
        mLogsDir = context.getFilesDir();
    }

    /**
     * Prints log values to disk
     */
    public void log(String tag, String msg) {
        String out = String.format("%s %s %s", DATE_FORMAT.format(new Date()), tag, msg);

        mHandler.post(() -> {
            synchronized (this) {
                PrintWriter writer = getWriter();
                if (writer != null) {
                    writer.println(out);
                }
            }
        });
    }

    private PrintWriter getWriter() {
        String fName = FILE_NAME_PREFIX + (LOG_DAYS % 10);
        if (fName.equals(mFileName)) return mCurrentWriter;

        Calendar cal = Calendar.getInstance();

        boolean append = false;
        File logFile = new File(mLogsDir, fName);
        if (logFile.exists()) {
            Calendar modifiedTime = Calendar.getInstance();
            modifiedTime.setTimeInMillis(logFile.lastModified());

            // If the file was modified more that 36 hours ago, purge the file.
            // We use instead of 24 to account for day-365 followed by day-1
            modifiedTime.add(Calendar.HOUR, 36);
            append = cal.before(modifiedTime);
        }


        if (mCurrentWriter != null) {
            mCurrentWriter.close();
        }
        try {
            mCurrentWriter = new PrintWriter(new FileWriter(logFile, append));
            mFileName = fName;
        } catch (Exception ex) {
            Log.e("HotseatLogs", "Error writing logs to file", ex);
            closeWriter();
        }
        return mCurrentWriter;
    }


    private synchronized void closeWriter() {
        mFileName = null;
        if (mCurrentWriter != null) {
            mCurrentWriter.close();
        }
        mCurrentWriter = null;
    }


    /**
     * Returns a list of all log files
     */
    public synchronized File[] getLogFiles() {
        File[] files = new File[LOG_DAYS + FileLog.LOG_DAYS];
        //include file log files here
        System.arraycopy(FileLog.getLogFiles(), 0, files, 0, FileLog.LOG_DAYS);

        closeWriter();
        for (int i = 0; i < LOG_DAYS; i++) {
            files[FileLog.LOG_DAYS + i] = new File(mLogsDir, FILE_NAME_PREFIX + i);
        }
        return files;
    }
}
Loading