From 6dc1cc2a7752f1efe642f677520febf10440756a Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Tue, 30 Oct 2018 11:55:15 +0800 Subject: [PATCH] Added the icon displayed on no account in search bar Mofidied the search_bar layout and added this icon in the right side of the search_bar. Added the hasAccount api in AvatarViewMixin and display this icon when there is no any account in device. Added the test case of the AvatarViewMixin. Bug: 117509285 Test: robotest Change-Id: I6ceaa457af4fb20acd0211ca840df5b530c47e0f --- res/drawable/ic_account_circle_24dp.xml | 27 ++++++ res/layout/search_bar.xml | 7 ++ res/values/dimens.xml | 3 + .../settings/accounts/AvatarViewMixin.java | 60 ++++++++++++ .../homepage/SettingsHomepageActivity.java | 6 ++ .../accounts/AvatarViewMixinTest.java | 94 +++++++++++++++++++ 6 files changed, 197 insertions(+) create mode 100644 res/drawable/ic_account_circle_24dp.xml create mode 100644 src/com/android/settings/accounts/AvatarViewMixin.java create mode 100644 tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java diff --git a/res/drawable/ic_account_circle_24dp.xml b/res/drawable/ic_account_circle_24dp.xml new file mode 100644 index 00000000000..8445adc5870 --- /dev/null +++ b/res/drawable/ic_account_circle_24dp.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml index 9e64db7295d..1ba64ad1ce0 100644 --- a/res/layout/search_bar.xml +++ b/res/layout/search_bar.xml @@ -45,5 +45,12 @@ android:layout_height="wrap_content" android:text="@string/search_menu"/> + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 9b33388e3b7..43cae81c384 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -103,6 +103,9 @@ 16dp 2dp 64dp + 32dp + 4dp + 16dp 16dp diff --git a/src/com/android/settings/accounts/AvatarViewMixin.java b/src/com/android/settings/accounts/AvatarViewMixin.java new file mode 100644 index 00000000000..d7f6f8aa836 --- /dev/null +++ b/src/com/android/settings/accounts/AvatarViewMixin.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 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.settings.accounts; + +import android.accounts.Account; +import android.content.Context; +import android.widget.ImageView; + +import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; + +import com.android.settings.R; +import com.android.settings.homepage.SettingsHomepageActivity; +import com.android.settings.overlay.FeatureFactory; + +/** + * Avatar related work to the onStart method of registered observable classes + * in {@link SettingsHomepageActivity}. + */ +public class AvatarViewMixin implements LifecycleObserver { + private Context mContext; + private ImageView mAvatarView; + + public AvatarViewMixin(Context context, ImageView avatarView) { + mContext = context.getApplicationContext(); + mAvatarView = avatarView; + } + + @OnLifecycleEvent(Lifecycle.Event.ON_START) + public void onStart() { + if (hasAccount()) { + //TODO(b/117509285): To migrate account icon on search bar + } else { + mAvatarView.setImageResource(R.drawable.ic_account_circle_24dp); + } + } + + @VisibleForTesting + boolean hasAccount() { + final Account accounts[] = FeatureFactory.getFactory( + mContext).getAccountFeatureProvider().getAccounts(mContext); + return (accounts != null) && (accounts.length > 0); + } +} diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index c10543dab6d..d3f11a0cc0b 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -19,6 +19,7 @@ package com.android.settings.homepage; import android.content.Intent; import android.os.Bundle; import android.util.FeatureFlagUtils; +import android.widget.ImageView; import android.widget.Toolbar; import androidx.fragment.app.Fragment; @@ -27,6 +28,7 @@ import androidx.fragment.app.FragmentTransaction; import com.android.settings.R; import com.android.settings.SettingsActivity; +import com.android.settings.accounts.AvatarViewMixin; import com.android.settings.core.FeatureFlags; import com.android.settings.core.SettingsBaseActivity; import com.android.settings.homepage.contextualcards.ContextualCardsFragment; @@ -51,6 +53,10 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { FeatureFactory.getFactory(this).getSearchFeatureProvider() .initSearchToolbar(this, toolbar); + final ImageView avatarView = findViewById(R.id.account_avatar); + final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView); + getLifecycle().addObserver(avatarViewMixin); + showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content); showFragment(new TopLevelSettings(), R.id.main_content); } diff --git a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java new file mode 100644 index 00000000000..c72561ed59c --- /dev/null +++ b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 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.settings.accounts; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.accounts.Account; +import android.content.Context; +import android.widget.ImageView; + +import com.android.settings.homepage.SettingsHomepageActivity; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.android.controller.ActivityController; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +@RunWith(SettingsRobolectricTestRunner.class) +public class AvatarViewMixinTest { + private static final String DUMMY_ACCOUNT = "test@domain.com"; + private static final String DUMMY_DOMAIN = "domain.com"; + + private Context mContext; + private ImageView mImageView; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mImageView = new ImageView(mContext); + } + + @Test + public void hasAccount_useDefaultAccountData_returnFalse() { + final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView); + assertThat(avatarViewMixin.hasAccount()).isFalse(); + } + + @Test + @Config(shadows = ShadowAccountFeatureProviderImpl.class) + public void hasAccount_useShadowAccountData_returnTrue() { + final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView); + assertThat(avatarViewMixin.hasAccount()).isTrue(); + } + + @Test + public void onStart_useMockAvatarViewMixin_shouldBeExecuted() { + final AvatarViewMixin mockAvatar = spy(new AvatarViewMixin(mContext, mImageView)); + + final ActivityController controller = Robolectric.buildActivity( + SettingsHomepageActivity.class).create(); + final SettingsHomepageActivity settingsHomepageActivity = + (SettingsHomepageActivity) controller.get(); + settingsHomepageActivity.getLifecycle().addObserver(mockAvatar); + controller.start(); + + verify(mockAvatar).onStart(); + } + + @Implements(AccountFeatureProviderImpl.class) + public static class ShadowAccountFeatureProviderImpl { + + @Implementation + public Account[] getAccounts(Context context) { + Account[] accounts = {new Account(DUMMY_ACCOUNT, DUMMY_DOMAIN)}; + return accounts; + } + } +}