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

Commit 8045e6c8 authored by Aaron Liu's avatar Aaron Liu Committed by Android (Google) Code Review
Browse files

Merge "User Switcher: Dynamically set max col" into tm-dev

parents 901dce08 c16c782b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@
    <dimen name="bouncer_user_switcher_icon_size">190dp</dimen>
    <dimen name="bouncer_user_switcher_icon_size_plus_margin">222dp</dimen>

    <dimen name="user_switcher_fullscreen_horizontal_gap">64dp</dimen>
    <dimen name="user_switcher_icon_selected_width">8dp</dimen>
    <dimen name="user_switcher_fullscreen_button_text_size">14sp</dimen>
    <dimen name="user_switcher_fullscreen_button_padding">12dp</dimen>
+3 −4
Original line number Diff line number Diff line
@@ -21,9 +21,8 @@
    android:id="@+id/user_switcher_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="40dp"
    android:layout_marginEnd="60dp"
    android:layout_marginStart="60dp">
    android:layout_marginVertical="40dp"
    android:layout_marginHorizontal="60dp">

  <androidx.constraintlayout.helper.widget.Flow
      android:id="@+id/flow"
@@ -36,7 +35,7 @@
      app:flow_horizontalBias="0.5"
      app:flow_verticalAlign="center"
      app:flow_wrapMode="chain"
      app:flow_horizontalGap="64dp"
      app:flow_horizontalGap="@dimen/user_switcher_fullscreen_horizontal_gap"
      app:flow_verticalGap="44dp"
      app:flow_horizontalStyle="packed"/>

+2 −2
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@
  <ImageView
      android:id="@+id/user_switcher_icon"
      android:layout_gravity="center"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" />
      android:layout_width="@dimen/bouncer_user_switcher_icon_size_plus_margin"
      android:layout_height="@dimen/bouncer_user_switcher_icon_size_plus_margin" />
  <TextView
      style="@style/Bouncer.UserSwitcher.Spinner.Item"
      android:id="@+id/user_switcher_text"
+42 −9
Original line number Diff line number Diff line
@@ -35,9 +35,8 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView

import androidx.constraintlayout.helper.widget.Flow

import com.android.internal.annotations.VisibleForTesting
import com.android.internal.util.UserIcons
import com.android.settingslib.Utils
import com.android.systemui.R
@@ -47,12 +46,12 @@ import com.android.systemui.plugins.FalsingManager.LOW_PENALTY
import com.android.systemui.statusbar.phone.ShadeController
import com.android.systemui.statusbar.policy.UserSwitcherController
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter
import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA
import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord
import com.android.systemui.util.LifecycleActivity

import javax.inject.Inject
import kotlin.math.ceil

private const val USER_VIEW = "user_view"

@@ -137,6 +136,18 @@ class UserSwitcherActivity @Inject constructor(
            return UserIcons.getDefaultUserIcon(resources, item.info.id, false)
        }

        fun getTotalUserViews(): Int {
            return users.count { item ->
                !doNotRenderUserView(item)
            }
        }

        fun doNotRenderUserView(item: UserRecord): Boolean {
            return item.isAddUser ||
                    item.isAddSupervisedUser ||
                    item.isGuest && item.info == null
        }

        private fun getDrawable(item: UserRecord): Drawable {
            var drawable = if (item.isCurrent && item.isGuest) {
                getDrawable(R.drawable.ic_avatar_guest_user)
@@ -211,7 +222,8 @@ class UserSwitcherActivity @Inject constructor(

        userSwitcherController.init(parent)
        initBroadcastReceiver()
        buildUserViews()

        parent.post { buildUserViews() }
    }

    private fun showPopupMenu() {
@@ -272,16 +284,32 @@ class UserSwitcherActivity @Inject constructor(
        }
        parent.removeViews(start, count)
        addUserRecords.clear()

        val flow = requireViewById<Flow>(R.id.flow)
        val totalWidth = parent.width
        val userViewCount = adapter.getTotalUserViews()
        val maxColumns = getMaxColumns(userViewCount)
        val horizontalGap = resources
            .getDimensionPixelSize(R.dimen.user_switcher_fullscreen_horizontal_gap)
        val totalWidthOfHorizontalGap = (maxColumns - 1) * horizontalGap
        val maxWidgetDiameter = (totalWidth - totalWidthOfHorizontalGap) / maxColumns

        flow.setMaxElementsWrap(maxColumns)

        for (i in 0 until adapter.getCount()) {
            val item = adapter.getItem(i)
            if (item.isAddUser ||
                item.isAddSupervisedUser ||
                item.isGuest && item.info == null) {
            if (adapter.doNotRenderUserView(item)) {
                addUserRecords.add(item)
            } else {
                val userView = adapter.getView(i, null, parent)
                userView.requireViewById<ImageView>(R.id.user_switcher_icon).apply {
                    val lp = layoutParams
                    if (maxWidgetDiameter < lp.width) {
                        lp.width = maxWidgetDiameter
                        lp.height = maxWidgetDiameter
                        layoutParams = lp
                    }
                }

                userView.setId(View.generateViewId())
                parent.addView(userView)

@@ -333,6 +361,11 @@ class UserSwitcherActivity @Inject constructor(
        broadcastDispatcher.registerReceiver(broadcastReceiver, filter)
    }

    @VisibleForTesting
    fun getMaxColumns(userCount: Int): Int {
        return if (userCount < 5) 4 else ceil(userCount / 2.0).toInt()
    }

    private class ItemAdapter(
        val parentContext: Context,
        val resource: Int,
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.systemui.user

import android.os.UserManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.LayoutInflater
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.phone.ShadeController
import com.android.systemui.statusbar.policy.UserSwitcherController
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations

@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
class UserSwitcherActivityTest : SysuiTestCase() {
    @Mock
    private lateinit var activity: UserSwitcherActivity
    @Mock
    private lateinit var userSwitcherController: UserSwitcherController
    @Mock
    private lateinit var broadcastDispatcher: BroadcastDispatcher
    @Mock
    private lateinit var layoutInflater: LayoutInflater
    @Mock
    private lateinit var falsingManager: FalsingManager
    @Mock
    private lateinit var userManager: UserManager
    @Mock
    private lateinit var shadeController: ShadeController

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        activity = UserSwitcherActivity(
            userSwitcherController,
            broadcastDispatcher,
            layoutInflater,
            falsingManager,
            userManager,
            shadeController
        )
    }

    @Test
    fun testMaxColumns() {
        assertThat(activity.getMaxColumns(3)).isEqualTo(4)
        assertThat(activity.getMaxColumns(4)).isEqualTo(4)
        assertThat(activity.getMaxColumns(5)).isEqualTo(3)
        assertThat(activity.getMaxColumns(6)).isEqualTo(3)
        assertThat(activity.getMaxColumns(7)).isEqualTo(4)
        assertThat(activity.getMaxColumns(9)).isEqualTo(5)
    }
}