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

Commit 64624ae4 authored by Angela Wang's avatar Angela Wang Committed by Android (Google) Code Review
Browse files

Merge "Update Flash Notifications screen with expressive design" into main

parents b5ec99bf 9736b59a
Loading
Loading
Loading
Loading
+20 −15
Original line number Diff line number Diff line
@@ -30,21 +30,26 @@
        settings:lottie_rawRes="@drawable/flash_notifications_illustration"
        settings:controller="com.android.settings.accessibility.FlashNotificationIllustrationPreferenceController" />

    <PreferenceCategory
        android:key="flash_notifications_category"
        android:layout="@layout/settingslib_preference_category_no_title">
        <SwitchPreferenceCompat
            android:key="camera_flash_notification_preference"
            android:persistent="false"
            android:title="@string/camera_flash_notification_title"
            settings:controller="com.android.settings.accessibility.CameraFlashNotificationPreferenceController" />

        <com.android.settingslib.PrimarySwitchPreference
            android:key="screen_flash_notification_preference"
            android:persistent="false"
            android:title="@string/screen_flash_notification_title"
            settings:controller="com.android.settings.accessibility.ScreenFlashNotificationPreferenceController" />
    </PreferenceCategory>

    <com.android.settings.accessibility.FlashNotificationsPreviewPreference
    <com.android.settingslib.widget.ButtonPreference
        android:key="flash_notifications_preview"
        android:title="@string/flash_notifications_preview"
        settings:buttonPreferenceSize="extra"
        settings:buttonPreferenceType="filled"
        settings:searchable="false"
        settings:controller="com.android.settings.accessibility.FlashNotificationsPreviewPreferenceController" />

+0 −94
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.accessibility;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.ColorInt;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;

import com.android.settings.R;
import com.android.settingslib.Utils;

/**
 * Preference for Flash notifications preview.
 */
public class FlashNotificationsPreviewPreference extends Preference {
    private Drawable mBackgroundEnabled;
    private Drawable mBackgroundDisabled;
    @ColorInt
    private int mTextColorDisabled;

    public FlashNotificationsPreviewPreference(Context context) {
        super(context);
        init();
    }

    public FlashNotificationsPreviewPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public FlashNotificationsPreviewPreference(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public FlashNotificationsPreviewPreference(Context context, AttributeSet attrs,
            int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        setLayoutResource(R.layout.flash_notification_preview_preference);
        mBackgroundEnabled = getContext().getDrawable(
                com.android.settingslib.widget.mainswitch.R.drawable.settingslib_switch_bar_bg_on);
        mBackgroundDisabled = getContext().getDrawable(R.drawable.switch_bar_bg_disabled);
        mTextColorDisabled = Utils.getColorAttrDefaultColor(getContext(),
                android.R.attr.textColorPrimary);
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);

        final boolean enabled = isEnabled();
        final View frame = holder.findViewById(R.id.frame);
        if (frame != null) {
            frame.setBackground(enabled ? mBackgroundEnabled : mBackgroundDisabled);
        }
        final TextView title = (TextView) holder.findViewById(android.R.id.title);
        if (title != null) {
            @ColorInt final int textColorEnabled = title.getCurrentTextColor();
            title.setAlpha(enabled ? 1f : 0.38f);
            title.setTextColor(enabled ? textColorEnabled : mTextColorDisabled);
        }
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        notifyChanged();
    }
}
+9 −13
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.ButtonPreference;

/**
 * Controller for flash notifications preview.
@@ -48,7 +49,7 @@ import com.android.settings.core.BasePreferenceController;
public class FlashNotificationsPreviewPreferenceController extends
        BasePreferenceController implements LifecycleEventObserver {

    private Preference mPreference;
    private ButtonPreference mPreference;
    private final ContentResolver mContentResolver;

    @VisibleForTesting
@@ -74,19 +75,14 @@ public class FlashNotificationsPreviewPreferenceController extends
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(getPreferenceKey());
        updateState(mPreference);
    }

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (getPreferenceKey().equals(preference.getKey())) {
        if (mPreference != null) {
            mPreference.setOnClickListener(view -> {
                Intent intent = new Intent(ACTION_FLASH_NOTIFICATION_START_PREVIEW);
                intent.putExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_SHORT_PREVIEW);
                mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
            return true;
            });
        }

        return super.handlePreferenceTreeClick(preference);
        updateState(mPreference);
    }

    @Override
+21 −28
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -37,13 +36,16 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.view.View;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.test.core.app.ApplicationProvider;

import com.android.settingslib.widget.ButtonPreference;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -51,7 +53,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -71,20 +72,21 @@ public class FlashNotificationsPreviewPreferenceControllerTest {
    private ContentResolver mContentResolver = mContext.getContentResolver();
    @Mock
    private PreferenceScreen mPreferenceScreen;
    private Preference mPreference;
    private ButtonPreference mPreference;
    private FlashNotificationsPreviewPreferenceController mController;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        when(mContext.getContentResolver()).thenReturn(mContentResolver);

        mPreference = new Preference(mContext);
        mPreference = new ButtonPreference(mContext);
        mPreference.setKey(PREFERENCE_KEY);
        final View rootView = View.inflate(mContext, mPreference.getLayoutResource(), null);
        mPreference.onBindViewHolder(PreferenceViewHolder.createInstanceForTests(rootView));
        when(mPreferenceScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);

        mController = new FlashNotificationsPreviewPreferenceController(mContext, PREFERENCE_KEY);
        mController.displayPreference(mPreferenceScreen);
    }

    @After
@@ -98,67 +100,58 @@ public class FlashNotificationsPreviewPreferenceControllerTest {
    }

    @Test
    public void testDisplayPreference_torchPresent_cameraOff_screenOff_notVisible() {
    public void updateState_cameraOff_screenOff_notVisible() {
        setFlashNotificationsState(FlashNotificationsUtil.State.OFF);

        mController.displayPreference(mPreferenceScreen);
        mController.updateState(mPreference);

        assertThat(mPreference.isVisible()).isFalse();
    }

    @Test
    public void testDisplayPreference_torchPresent_cameraOn_screenOff_isVisible() {
    public void updateState_cameraOn_screenOff_isVisible() {
        setFlashNotificationsState(FlashNotificationsUtil.State.CAMERA);

        mController.displayPreference(mPreferenceScreen);
        mController.updateState(mPreference);

        assertThat(mPreference.isVisible()).isTrue();
    }

    @Test
    public void testDisplayPreference_torchPresent_cameraOff_screenOn_isVisible() {
    public void updateState_cameraOff_screenOn_isVisible() {
        setFlashNotificationsState(FlashNotificationsUtil.State.SCREEN);

        mController.displayPreference(mPreferenceScreen);
        mController.updateState(mPreference);

        assertThat(mPreference.isVisible()).isTrue();
    }

    @Test
    public void testDisplayPreference_torchPresent_cameraOn_screenOn_isVisible() {
    public void updateState_cameraOn_screenOn_isVisible() {
        setFlashNotificationsState(FlashNotificationsUtil.State.CAMERA_SCREEN);

        mController.displayPreference(mPreferenceScreen);
        mController.updateState(mPreference);

        assertThat(mPreference.isVisible()).isTrue();
    }

    @Test
    public void testHandlePreferenceTreeClick_invalidPreference() {
        mController.handlePreferenceTreeClick(mock(Preference.class));

        verify(mContext, never()).sendBroadcastAsUser(any(), any());
    }

    @Test
    public void handlePreferenceTreeClick_assertAction() {
        mController.handlePreferenceTreeClick(mPreference);
    public void clickOnButton_assertAction() {
        mPreference.getButton().callOnClick();

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcastAsUser(captor.capture(), any());
        Intent captured = captor.getValue();

        assertThat(captured.getAction()).isEqualTo(ACTION_FLASH_NOTIFICATION_START_PREVIEW);
    }

    @Test
    public void handlePreferenceTreeClick_assertExtra() {
        mController.handlePreferenceTreeClick(mPreference);
    public void clickOnButton_assertExtra() {
        mPreference.getButton().callOnClick();

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcastAsUser(captor.capture(), any());
        Intent captured = captor.getValue();

        assertThat(captured.getIntExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_LONG_PREVIEW))
                .isEqualTo(TYPE_SHORT_PREVIEW);
    }
+0 −93
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.accessibility;

import static com.google.common.truth.Truth.assertThat;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.ColorInt;
import androidx.preference.PreferenceViewHolder;
import androidx.test.core.app.ApplicationProvider;

import com.android.settings.R;
import com.android.settingslib.Utils;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;

@RunWith(RobolectricTestRunner.class)
public class FlashNotificationsPreviewPreferenceTest {

    @Rule
    public MockitoRule mMockitoRule = MockitoJUnit.rule();
    @Spy
    private final Context mContext = ApplicationProvider.getApplicationContext();
    private FlashNotificationsPreviewPreference mFlashNotificationsPreviewPreference;
    private PreferenceViewHolder mPreferenceViewHolder;

    @Before
    public void setUp() {
        mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(
                LayoutInflater.from(mContext).inflate(
                        R.layout.flash_notification_preview_preference, null));
        mFlashNotificationsPreviewPreference = new FlashNotificationsPreviewPreference(mContext);
    }

    @Test
    public void setEnabled_true_verifyEnabledUi() {
        @ColorInt final int textColorEnabled = ((TextView) mPreferenceViewHolder.findViewById(
                android.R.id.title)).getCurrentTextColor();

        mFlashNotificationsPreviewPreference.setEnabled(true);
        mFlashNotificationsPreviewPreference.onBindViewHolder(mPreferenceViewHolder);

        final View frame = mPreferenceViewHolder.findViewById(R.id.frame);
        final int backgroundResId = Shadows.shadowOf(frame.getBackground()).getCreatedFromResId();
        assertThat(backgroundResId).isEqualTo(
                com.android.settingslib.widget.mainswitch.R.drawable.settingslib_switch_bar_bg_on);
        final TextView title = (TextView) mPreferenceViewHolder.findViewById(android.R.id.title);
        assertThat(title.getAlpha()).isEqualTo(1f);
        assertThat(title.getCurrentTextColor()).isEqualTo(textColorEnabled);
    }

    @Test
    public void setEnabled_false_verifyDisabledUi() {
        @ColorInt final int textColorDisabled = Utils.getColorAttrDefaultColor(mContext,
                android.R.attr.textColorPrimary);

        mFlashNotificationsPreviewPreference.setEnabled(false);
        mFlashNotificationsPreviewPreference.onBindViewHolder(mPreferenceViewHolder);

        final View frame = mPreferenceViewHolder.findViewById(R.id.frame);
        final int backgroundResId = Shadows.shadowOf(frame.getBackground()).getCreatedFromResId();
        assertThat(backgroundResId).isEqualTo(R.drawable.switch_bar_bg_disabled);
        final TextView title = (TextView) mPreferenceViewHolder.findViewById(android.R.id.title);
        assertThat(title.getAlpha()).isEqualTo(0.38f);
        assertThat(title.getCurrentTextColor()).isEqualTo(textColorDisabled);
    }
}
 No newline at end of file