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

Commit ee9fc3bf authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/31154470',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/31154470', 'googleplex-android-review.googlesource.com/31195717', 'googleplex-android-review.googlesource.com/31014284', 'googleplex-android-review.googlesource.com/31395613', 'googleplex-android-review.googlesource.com/31569659'] into 25Q1-release.

Change-Id: I446aae829c6c9c29b5d7808787dba8f1b68c361b
parents faa94665 dbfc3ce2
Loading
Loading
Loading
Loading
+24 −23
Original line number Diff line number Diff line
@@ -2951,9 +2951,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            final int transitType = info.getType();
            TransitionInfo.Change pipChange = null;
            int closingSplitTaskId = -1;
            // This array tracks if we are sending stages TO_BACK in this transition.
            // TODO (b/349828130): Update for n apps
            boolean[] stagesSentToBack = new boolean[2];
            // This array tracks where we are sending stages (TO_BACK/TO_FRONT) in this transition.
            // TODO (b/349828130): Update for n apps (needs to handle different indices than 0/1).
            //  Also make sure having multiple changes per stage (2+ tasks in one stage) is being
            //  handled properly.
            int[] stageChanges = new int[2];

            for (int iC = 0; iC < info.getChanges().size(); ++iC) {
                final TransitionInfo.Change change = info.getChanges().get(iC);
@@ -3016,18 +3018,25 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                                + " with " + taskId + " before startAnimation().");
                    }
                }
                if (isClosingType(change.getMode()) &&
                        getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED) {

                    // Record which stages are getting sent to back
                    if (change.getMode() == TRANSIT_TO_BACK) {
                        stagesSentToBack[getStageOfTask(taskId)] = true;
                final int stageOfTaskId = getStageOfTask(taskId);
                if (stageOfTaskId == STAGE_TYPE_UNDEFINED) {
                    continue;
                }

                if (isClosingType(change.getMode())) {
                    // (For PiP transitions) If either one of the 2 stages is closing we're assuming
                    // we'll break split
                    closingSplitTaskId = taskId;
                }
                if (transitType == WindowManager.TRANSIT_WAKE) {
                    // Record which stages are receiving which changes
                    if ((change.getMode() == TRANSIT_TO_BACK
                            || change.getMode() == TRANSIT_TO_FRONT)
                            && (stageOfTaskId == STAGE_TYPE_MAIN
                            || stageOfTaskId == STAGE_TYPE_SIDE)) {
                        stageChanges[stageOfTaskId] = change.getMode();
                    }
                }
            }

            if (pipChange != null) {
@@ -3052,19 +3061,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                return true;
            }

            // If keyguard is active, check to see if we have our TO_BACK transitions in order.
            // This array should either be all false (no split stages sent to back) or all true
            // (all stages sent to back). In any other case (which can happen with SHOW_ABOVE_LOCKED
            // apps) we should break split.
            if (mKeyguardActive) {
                boolean isFirstStageSentToBack = stagesSentToBack[0];
                for (boolean b : stagesSentToBack) {
                    // Compare each boolean to the first one. If any are different, break split.
                    if (b != isFirstStageSentToBack) {
            // If keyguard is active, check to see if we have all our stages showing. If one stage
            // was moved but not the other (which can happen with SHOW_ABOVE_LOCKED apps), we should
            // break split.
            if (mKeyguardActive && stageChanges[STAGE_TYPE_MAIN] != stageChanges[STAGE_TYPE_SIDE]) {
                dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
                        break;
                    }
                }
            }

            final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
+8 −1
Original line number Diff line number Diff line
@@ -19,10 +19,11 @@ package com.android.systemui.shared.recents;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.view.MotionEvent;
import com.android.systemui.shared.recents.ISystemUiProxy;

// Next ID: 34
// Next ID: 36
oneway interface IOverviewProxy {

    void onActiveNavBarRegionChanges(in Region activeRegion) = 11;
@@ -137,4 +138,10 @@ oneway interface IOverviewProxy {
     * Sent when {@link TaskbarDelegate#appTransitionPending} is called.
     */
    void appTransitionPending(boolean pending) = 34;

    /**
     * Sent right after OverviewProxy calls unbindService() on the TouchInteractionService.
     * TouchInteractionService is expected to send the reply once it has finished cleaning up.
     */
    void onUnbind(IRemoteCallback reply) = 35;
}
+14 −10
Original line number Diff line number Diff line
@@ -20,10 +20,12 @@ import android.content.Context
import android.hardware.input.InputManager
import android.hardware.input.KeyGestureEvent
import androidx.datastore.core.DataStore
import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.preferences.core.MutablePreferences
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.preferencesDataStoreFile
@@ -68,7 +70,7 @@ interface ContextualEducationRepository {

    suspend fun updateGestureEduModel(
        gestureType: GestureType,
        transform: (GestureEduModel) -> GestureEduModel
        transform: (GestureEduModel) -> GestureEduModel,
    )

    suspend fun updateEduDeviceConnectionTime(
@@ -149,6 +151,8 @@ constructor(
                        String.format(DATASTORE_DIR, userId)
                    )
                },
                corruptionHandler =
                    ReplaceFileCorruptionHandler(produceNewData = { emptyPreferences() }),
                scope = newDsScope,
            )
        dataStoreScope = newDsScope
@@ -159,7 +163,7 @@ constructor(

    private fun getGestureEduModel(
        gestureType: GestureType,
        preferences: Preferences
        preferences: Preferences,
    ): GestureEduModel {
        return GestureEduModel(
            signalCount = preferences[getSignalCountKey(gestureType)] ?: 0,
@@ -183,7 +187,7 @@ constructor(

    override suspend fun updateGestureEduModel(
        gestureType: GestureType,
        transform: (GestureEduModel) -> GestureEduModel
        transform: (GestureEduModel) -> GestureEduModel,
    ) {
        datastore.filterNotNull().first().edit { preferences ->
            val currentModel = getGestureEduModel(gestureType, preferences)
@@ -193,17 +197,17 @@ constructor(
            setInstant(
                preferences,
                updatedModel.lastShortcutTriggeredTime,
                getLastShortcutTriggeredTimeKey(gestureType)
                getLastShortcutTriggeredTimeKey(gestureType),
            )
            setInstant(
                preferences,
                updatedModel.usageSessionStartTime,
                getUsageSessionStartTimeKey(gestureType)
                getUsageSessionStartTimeKey(gestureType),
            )
            setInstant(
                preferences,
                updatedModel.lastEducationTime,
                getLastEducationTimeKey(gestureType)
                getLastEducationTimeKey(gestureType),
            )
        }
    }
@@ -220,12 +224,12 @@ constructor(
            setInstant(
                preferences,
                updatedModel.keyboardFirstConnectionTime,
                getKeyboardFirstConnectionTimeKey()
                getKeyboardFirstConnectionTimeKey(),
            )
            setInstant(
                preferences,
                updatedModel.touchpadFirstConnectionTime,
                getTouchpadFirstConnectionTimeKey()
                getTouchpadFirstConnectionTimeKey(),
            )
        }
    }
@@ -235,7 +239,7 @@ constructor(
            keyboardFirstConnectionTime =
                preferences[getKeyboardFirstConnectionTimeKey()]?.let { Instant.ofEpochSecond(it) },
            touchpadFirstConnectionTime =
                preferences[getTouchpadFirstConnectionTimeKey()]?.let { Instant.ofEpochSecond(it) }
                preferences[getTouchpadFirstConnectionTimeKey()]?.let { Instant.ofEpochSecond(it) },
        )
    }

@@ -263,7 +267,7 @@ constructor(
    private fun setInstant(
        preferences: MutablePreferences,
        instant: Instant?,
        key: Preferences.Key<Long>
        key: Preferences.Key<Long>,
    ) {
        if (instant != null) {
            // Use epochSecond because an instant is defined as a signed long (64bit number) of
+8 −1
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@ package com.android.systemui.inputdevice.tutorial.data.repository

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.android.systemui.dagger.SysUISingleton
@@ -45,7 +47,12 @@ class TutorialSchedulerRepository(
    ) : this(applicationContext, backgroundScope, dataStoreName = DATASTORE_NAME)

    private val Context.dataStore: DataStore<Preferences> by
        preferencesDataStore(name = dataStoreName, scope = backgroundScope)
        preferencesDataStore(
            name = dataStoreName,
            corruptionHandler =
                ReplaceFileCorruptionHandler(produceNewData = { emptyPreferences() }),
            scope = backgroundScope,
        )

    suspend fun isLaunched(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.isLaunched

+104 −86
Original line number Diff line number Diff line
@@ -86,15 +86,56 @@ class ClockSizeTransition(
            transition.values[SMARTSPACE_BOUNDS] = targetSSView.getRect()
        }

        open fun mutateBounds(
            view: View,
            fromIsVis: Boolean,
            toIsVis: Boolean,
            fromBounds: Rect,
            toBounds: Rect,
            fromSSBounds: Rect?,
            toSSBounds: Rect?,
        ) {}
        open fun initTargets(from: Target, to: Target) {}

        open fun mutateTargets(from: Target, to: Target) {}

        data class Target(
            var view: View,
            var visibility: Int,
            var isVisible: Boolean,
            var alpha: Float,
            var bounds: Rect,
            var ssBounds: Rect?,
        ) {
            companion object {
                fun fromStart(startValues: TransitionValues): Target {
                    var fromVis = startValues.values[PROP_VISIBILITY] as Int
                    var fromIsVis = fromVis == View.VISIBLE
                    var fromAlpha = startValues.values[PROP_ALPHA] as Float

                    // Align starting visibility and alpha
                    if (!fromIsVis) fromAlpha = 0f
                    else if (fromAlpha <= 0f) {
                        fromIsVis = false
                        fromVis = View.INVISIBLE
                    }

                    return Target(
                        view = startValues.view,
                        visibility = fromVis,
                        isVisible = fromIsVis,
                        alpha = fromAlpha,
                        bounds = startValues.values[PROP_BOUNDS] as Rect,
                        ssBounds = startValues.values[SMARTSPACE_BOUNDS] as Rect?,
                    )
                }

                fun fromEnd(endValues: TransitionValues): Target {
                    val toVis = endValues.values[PROP_VISIBILITY] as Int
                    val toIsVis = toVis == View.VISIBLE

                    return Target(
                        view = endValues.view,
                        visibility = toVis,
                        isVisible = toIsVis,
                        alpha = if (toIsVis) 1f else 0f,
                        bounds = endValues.values[PROP_BOUNDS] as Rect,
                        ssBounds = endValues.values[SMARTSPACE_BOUNDS] as Rect?,
                    )
                }
            }
        }

        override fun createAnimator(
            sceenRoot: ViewGroup,
@@ -109,72 +150,58 @@ class ClockSizeTransition(
                return null
            }

            var fromVis = startValues.values[PROP_VISIBILITY] as Int
            var fromIsVis = fromVis == View.VISIBLE
            var fromAlpha = startValues.values[PROP_ALPHA] as Float
            val fromBounds = startValues.values[PROP_BOUNDS] as Rect
            val fromSSBounds = startValues.values[SMARTSPACE_BOUNDS] as Rect?

            val toView = endValues.view
            val toVis = endValues.values[PROP_VISIBILITY] as Int
            val toBounds = endValues.values[PROP_BOUNDS] as Rect
            val toSSBounds = endValues.values[SMARTSPACE_BOUNDS] as Rect?
            val toIsVis = toVis == View.VISIBLE
            val toAlpha = if (toIsVis) 1f else 0f
            val from = Target.fromStart(startValues)
            val to = Target.fromEnd(endValues)
            initTargets(from, to)
            mutateTargets(from, to)

            // Align starting visibility and alpha
            if (!fromIsVis) fromAlpha = 0f
            else if (fromAlpha <= 0f) {
                fromIsVis = false
                fromVis = View.INVISIBLE
            }

            mutateBounds(toView, fromIsVis, toIsVis, fromBounds, toBounds, fromSSBounds, toSSBounds)
            if (fromIsVis == toIsVis && fromBounds.equals(toBounds)) {
            if (from.isVisible == to.isVisible && from.bounds.equals(to.bounds)) {
                if (DEBUG) {
                    Log.w(
                        TAG,
                        "Skipping no-op transition: $toView; " +
                            "vis: $fromVis -> $toVis; " +
                            "alpha: $fromAlpha -> $toAlpha; " +
                            "bounds: $fromBounds -> $toBounds; ",
                        "Skipping no-op transition: ${to.view}; " +
                            "vis: ${from.visibility} -> ${to.visibility}; " +
                            "alpha: ${from.alpha} -> ${to.alpha}; " +
                            "bounds: ${from.bounds} -> ${to.bounds}; ",
                    )
                }
                return null
            }

            val sendToBack = fromIsVis && !toIsVis
            val sendToBack = from.isVisible && !to.isVisible
            fun lerp(start: Int, end: Int, fract: Float): Int =
                MathUtils.lerp(start.toFloat(), end.toFloat(), fract).toInt()
            fun computeBounds(fract: Float): Rect =
                Rect(
                    lerp(fromBounds.left, toBounds.left, fract),
                    lerp(fromBounds.top, toBounds.top, fract),
                    lerp(fromBounds.right, toBounds.right, fract),
                    lerp(fromBounds.bottom, toBounds.bottom, fract),
                    lerp(from.bounds.left, to.bounds.left, fract),
                    lerp(from.bounds.top, to.bounds.top, fract),
                    lerp(from.bounds.right, to.bounds.right, fract),
                    lerp(from.bounds.bottom, to.bounds.bottom, fract),
                )

            fun assignAnimValues(src: String, fract: Float, vis: Int? = null) {
                mutateTargets(from, to)
                val bounds = computeBounds(fract)
                val alpha = MathUtils.lerp(fromAlpha, toAlpha, fract)
                val alpha = MathUtils.lerp(from.alpha, to.alpha, fract)
                if (DEBUG) {
                    Log.i(
                        TAG,
                        "$src: $toView; fract=$fract; alpha=$alpha; vis=$vis; bounds=$bounds;",
                        "$src: ${to.view}; fract=$fract; alpha=$alpha; vis=$vis; bounds=$bounds;",
                    )
                }
                toView.setVisibility(vis ?: View.VISIBLE)
                toView.setAlpha(alpha)
                toView.setRect(bounds)

                to.view.setVisibility(vis ?: View.VISIBLE)
                to.view.setAlpha(alpha)
                to.view.setRect(bounds)
            }

            if (DEBUG) {
                Log.i(
                    TAG,
                    "transitioning: $toView; " +
                        "vis: $fromVis -> $toVis; " +
                        "alpha: $fromAlpha -> $toAlpha; " +
                        "bounds: $fromBounds -> $toBounds; ",
                    "transitioning: ${to.view}; " +
                        "vis: ${from.visibility} -> ${to.visibility}; " +
                        "alpha: ${from.alpha} -> ${to.alpha}; " +
                        "bounds: ${from.bounds} -> ${to.bounds}; ",
                )
            }

@@ -190,11 +217,11 @@ class ClockSizeTransition(
                this@VisibilityBoundsTransition.addListener(
                    object : TransitionListenerAdapter() {
                        override fun onTransitionStart(t: Transition) {
                            toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
                            to.view.viewTreeObserver.addOnPreDrawListener(predrawCallback)
                        }

                        override fun onTransitionEnd(t: Transition) {
                            toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
                            to.view.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
                        }
                    }
                )
@@ -202,17 +229,17 @@ class ClockSizeTransition(
                val listener =
                    object : AnimatorListenerAdapter() {
                        override fun onAnimationStart(anim: Animator) {
                            assignAnimValues("start", 0f, fromVis)
                            assignAnimValues("start", 0f, from.visibility)
                        }

                        override fun onAnimationEnd(anim: Animator) {
                            assignAnimValues("end", 1f, toVis)
                            if (sendToBack) toView.translationZ = 0f
                            assignAnimValues("end", 1f, to.visibility)
                            if (sendToBack) to.view.translationZ = 0f
                        }
                    }

                anim.addListener(listener)
                assignAnimValues("init", 0f, fromVis)
                assignAnimValues("init", 0f, from.visibility)
            }
        }

@@ -251,31 +278,23 @@ class ClockSizeTransition(
            }
        }

        override fun mutateBounds(
            view: View,
            fromIsVis: Boolean,
            toIsVis: Boolean,
            fromBounds: Rect,
            toBounds: Rect,
            fromSSBounds: Rect?,
            toSSBounds: Rect?,
        ) {
        override fun initTargets(from: Target, to: Target) {
            // Move normally if clock is not changing visibility
            if (fromIsVis == toIsVis) return
            if (from.isVisible == to.isVisible) return

            fromBounds.set(toBounds)
            from.bounds.set(to.bounds)
            if (isLargeClock) {
                // Large clock shouldn't move; fromBounds already set
            } else if (toSSBounds != null && fromSSBounds != null) {
            } else if (to.ssBounds != null && from.ssBounds != null) {
                // Instead of moving the small clock the full distance, we compute the distance
                // smartspace will move. We then scale this to match the duration of this animation
                // so that the small clock moves at the same speed as smartspace.
                val ssTranslation =
                    abs((toSSBounds.top - fromSSBounds.top) * smallClockMoveScale).toInt()
                fromBounds.top = toBounds.top - ssTranslation
                fromBounds.bottom = toBounds.bottom - ssTranslation
                    abs((to.ssBounds!!.top - from.ssBounds!!.top) * smallClockMoveScale).toInt()
                from.bounds.top = to.bounds.top - ssTranslation
                from.bounds.bottom = to.bounds.bottom - ssTranslation
            } else {
                Log.e(TAG, "mutateBounds: smallClock received no smartspace bounds")
                Log.e(TAG, "initTargets: smallClock received no smartspace bounds")
            }
        }
    }
@@ -320,10 +339,9 @@ class ClockSizeTransition(
        }
    }

    // TODO: Might need a mechanism to update this one while in-progress
    class SmartspaceMoveTransition(
        val config: IntraBlueprintTransition.Config,
        viewModel: KeyguardClockViewModel,
        val viewModel: KeyguardClockViewModel,
    ) : VisibilityBoundsTransition() {
        private val isLargeClock = viewModel.isLargeClockVisible.value
        override val captureSmartspace = false
@@ -340,23 +358,23 @@ class ClockSizeTransition(
            addTarget(R.id.status_view_media_container)
        }

        override fun mutateBounds(
            view: View,
            fromIsVis: Boolean,
            toIsVis: Boolean,
            fromBounds: Rect,
            toBounds: Rect,
            fromSSBounds: Rect?,
            toSSBounds: Rect?,
        ) {
        override fun initTargets(from: Target, to: Target) {
            // If view is changing visibility, hold it in place
            if (fromIsVis == toIsVis) return
            if (DEBUG) Log.i(TAG, "Holding position of ${view.id}")
            if (from.isVisible == to.isVisible) return
            if (DEBUG) Log.i(TAG, "Holding position of ${to.view.id}")

            if (fromIsVis) {
                toBounds.set(fromBounds)
            if (from.isVisible) {
                to.bounds.set(from.bounds)
            } else {
                fromBounds.set(toBounds)
                from.bounds.set(to.bounds)
            }
        }

        override fun mutateTargets(from: Target, to: Target) {
            if (to.view.id == sharedR.id.date_smartspace_view) {
                to.isVisible = !viewModel.hasCustomWeatherDataDisplay.value
                to.visibility = if (to.isVisible) View.VISIBLE else View.GONE
                to.alpha = if (to.isVisible) 1f else 0f
            }
        }

Loading