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

Commit 1e4d5b58 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Refactor Work sounds in SoundSettings."

parents d8c209f0 2adb6ea4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -16,8 +16,12 @@

package com.android.settings.notification;

import android.annotation.UserIdInt;
import android.content.Context;
import android.media.AudioSystem;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.settings.Utils;

/**
 * Helper class to wrap API for testing
@@ -34,4 +38,11 @@ public class AudioHelper {
        return AudioSystem.isSingleVolume(mContext);
    }

    public int getManagedProfileId(UserManager um) {
        return Utils.getManagedProfileId(um, UserHandle.myUserId());
    }

    public Context createPackageContextAsUser(@UserIdInt int profileId) {
        return Utils.createPackageContextAsUser(mContext, profileId);
    }
}
+9 −249
Original line number Diff line number Diff line
@@ -16,45 +16,26 @@

package com.android.settings.notification;

import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.SeekBarVolumizer;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.TwoStatePreference;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
import com.android.settings.DefaultRingtonePreference;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
@@ -66,16 +47,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SoundSettings extends DashboardFragment
        implements OnPreferenceChangeListener {
public class SoundSettings extends DashboardFragment {
    private static final String TAG = "SoundSettings";

    private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
    private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
    private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
    private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone";
    private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone";

    private static final String SELECTED_PREFERENCE_KEY = "selected_preference";
    private static final int REQUEST_CODE = 200;

@@ -84,20 +58,9 @@ public class SoundSettings extends DashboardFragment
    private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback();
    private final H mHandler = new H();

    private Context mContext;
    private boolean mVoiceCapable;

    private PreferenceGroup mWorkPreferenceCategory;
    private TwoStatePreference mWorkUsePersonalSounds;
    private Preference mWorkPhoneRingtonePreference;
    private Preference mWorkNotificationRingtonePreference;
    private Preference mWorkAlarmRingtonePreference;

    private UserManager mUserManager;
    private WorkSoundPreferenceController mWorkSoundController;
    private RingtonePreference mRequestPreference;

    private @UserIdInt int mManagedProfileId;

    @Override
    public int getMetricsCategory() {
        return MetricsEvent.SOUND;
@@ -106,10 +69,6 @@ public class SoundSettings extends DashboardFragment
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = getActivity();
        mUserManager = UserManager.get(getContext());
        mVoiceCapable = Utils.isVoiceCapable(mContext);

        if (savedInstanceState != null) {
            String selectedPreference = savedInstanceState.getString(SELECTED_PREFERENCE_KEY, null);
            if (!TextUtils.isEmpty(selectedPreference)) {
@@ -118,25 +77,6 @@ public class SoundSettings extends DashboardFragment
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        mManagedProfileId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
        if (mManagedProfileId != UserHandle.USER_NULL && shouldShowRingtoneSettings()) {
            if ((mWorkPreferenceCategory == null)) {
                // Work preferences not yet set
                addPreferencesFromResource(R.xml.sound_work_settings);
                initWorkPreferences();
            }
            if (!mWorkUsePersonalSounds.isChecked()) {
                updateWorkRingtoneSummaries();
            }
        } else {
            maybeRemoveWorkPreferences();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
@@ -190,6 +130,10 @@ public class SoundSettings extends DashboardFragment
        controllers.add(new AlarmRingtonePreferenceController(context));
        controllers.add(new NotificationRingtonePreferenceController(context));

        // === Work Sound Settings ===
        mWorkSoundController = new WorkSoundPreferenceController(context, this, getLifecycle());
        controllers.add(mWorkSoundController);

        return controllers;
    }

@@ -209,33 +153,6 @@ public class SoundSettings extends DashboardFragment
        }
    }

    /**
     * Updates the summary of work preferences
     *
     * This fragment only listens to changes on the work ringtone preferences, identified by keys
     * "work_ringtone", "work_notification_ringtone" and "work_alarm_ringtone".
     *
     * Note: Changes to the personal ringtones aren't listened to this way because they were already
     * handled using a {@link #SettingsObserver} ContentObserver. This wouldn't be appropriate for
     * work settings since the Settings app runs on the personal user.
     */
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        int ringtoneType;
        if (KEY_WORK_PHONE_RINGTONE.equals(preference.getKey())) {
            ringtoneType = RingtoneManager.TYPE_RINGTONE;
        } else if (KEY_WORK_NOTIFICATION_RINGTONE.equals(preference.getKey())) {
            ringtoneType = RingtoneManager.TYPE_NOTIFICATION;
        } else if (KEY_WORK_ALARM_RINGTONE.equals(preference.getKey())) {
            ringtoneType = RingtoneManager.TYPE_ALARM;
        } else {
            return true;
        }

        preference.setSummary(updateRingtoneName(getManagedProfileContext(), ringtoneType));
        return true;
    }

    // === Volumes ===

    final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback {
@@ -265,23 +182,6 @@ public class SoundSettings extends DashboardFragment
        }
    };


    // === Phone & notification ringtone ===

    private boolean shouldShowRingtoneSettings() {
        return !AudioSystem.isSingleVolume(mContext);
    }

    private static CharSequence updateRingtoneName(Context context, int type) {
        if (context == null) {
            Log.e(TAG, "Unable to update ringtone name, no context provided");
            return null;
        }
        Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
        return Ringtone.getTitle(context, ringtoneUri, false /* followSettingsUri */,
                true /* allowRemote */);
    }

    // === Callbacks ===


@@ -393,149 +293,9 @@ public class SoundSettings extends DashboardFragment

    // === Work Sound Settings ===

    private Context getManagedProfileContext() {
        if (mManagedProfileId == UserHandle.USER_NULL) {
            return null;
        }
        return Utils.createPackageContextAsUser(mContext, mManagedProfileId);
    }

    private DefaultRingtonePreference initWorkPreference(String key) {
        DefaultRingtonePreference pref =
                (DefaultRingtonePreference) getPreferenceScreen().findPreference(key);
        pref.setOnPreferenceChangeListener(this);

        // Required so that RingtonePickerActivity lists the work profile ringtones
        pref.setUserId(mManagedProfileId);
        return pref;
    }

    private void initWorkPreferences() {
        mWorkPreferenceCategory = (PreferenceGroup) getPreferenceScreen()
                .findPreference(KEY_WORK_CATEGORY);
        mWorkUsePersonalSounds = (TwoStatePreference) getPreferenceScreen()
                .findPreference(KEY_WORK_USE_PERSONAL_SOUNDS);
        mWorkPhoneRingtonePreference = initWorkPreference(KEY_WORK_PHONE_RINGTONE);
        mWorkNotificationRingtonePreference = initWorkPreference(KEY_WORK_NOTIFICATION_RINGTONE);
        mWorkAlarmRingtonePreference = initWorkPreference(KEY_WORK_ALARM_RINGTONE);

        if (!mVoiceCapable) {
            mWorkPreferenceCategory.removePreference(mWorkPhoneRingtonePreference);
            mWorkPhoneRingtonePreference = null;
        }

        Context managedProfileContext = getManagedProfileContext();
        if (Settings.Secure.getIntForUser(managedProfileContext.getContentResolver(),
                Settings.Secure.SYNC_PARENT_SOUNDS, 0, mManagedProfileId) == 1) {
            enableWorkSyncSettings();
        } else {
            disableWorkSyncSettings();
        }

        mWorkUsePersonalSounds.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                if ((boolean) newValue) {
                    UnifyWorkDialogFragment.show(SoundSettings.this);
                    return false;
                } else {
                    disableWorkSync();
                    return true;
                }
            }
        });
    }

    private void enableWorkSync() {
        RingtoneManager.enableSyncFromParent(getManagedProfileContext());
        enableWorkSyncSettings();
    }

    private void enableWorkSyncSettings() {
        mWorkUsePersonalSounds.setChecked(true);

        if (mWorkPhoneRingtonePreference != null) {
            mWorkPhoneRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
        }
        mWorkNotificationRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
        mWorkAlarmRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
    }

    private void disableWorkSync() {
        RingtoneManager.disableSyncFromParent(getManagedProfileContext());
        disableWorkSyncSettings();
    }

    private void disableWorkSyncSettings() {
        if (mWorkPhoneRingtonePreference != null) {
            mWorkPhoneRingtonePreference.setEnabled(true);
        }
        mWorkNotificationRingtonePreference.setEnabled(true);
        mWorkAlarmRingtonePreference.setEnabled(true);

        updateWorkRingtoneSummaries();
    }

    private void updateWorkRingtoneSummaries() {
        Context managedProfileContext = getManagedProfileContext();

        if (mWorkPhoneRingtonePreference != null) {
            mWorkPhoneRingtonePreference.setSummary(
                    updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_RINGTONE));
        }
        mWorkNotificationRingtonePreference.setSummary(
                updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_NOTIFICATION));
        mWorkAlarmRingtonePreference.setSummary(
                updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_ALARM));
    }

    private void maybeRemoveWorkPreferences() {
        if (mWorkPreferenceCategory == null) {
            // No work preferences to remove
            return;
        }
        getPreferenceScreen().removePreference(mWorkPreferenceCategory);
        mWorkPreferenceCategory = null;
        mWorkPhoneRingtonePreference = null;
        mWorkNotificationRingtonePreference = null;
        mWorkAlarmRingtonePreference = null;
    }

    public static class UnifyWorkDialogFragment extends InstrumentedDialogFragment
            implements DialogInterface.OnClickListener {
        private static final String TAG = "UnifyWorkDialogFragment";
        private static final int REQUEST_CODE = 200;

        @Override
        public int getMetricsCategory() {
            return MetricsEvent.DIALOG_UNIFY_SOUND_SETTINGS;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return new AlertDialog.Builder(getActivity())
                    .setTitle(R.string.work_sync_dialog_title)
                    .setMessage(R.string.work_sync_dialog_message)
                    .setPositiveButton(R.string.work_sync_dialog_yes, UnifyWorkDialogFragment.this)
                    .setNegativeButton(android.R.string.no, null)
                    .create();
        }

        public static void show(SoundSettings parent) {
            FragmentManager fm = parent.getFragmentManager();
            if (fm.findFragmentByTag(TAG) == null) {
                UnifyWorkDialogFragment fragment = new UnifyWorkDialogFragment();
                fragment.setTargetFragment(parent, REQUEST_CODE);
                fragment.show(fm, TAG);
            }
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
            SoundSettings soundSettings = (SoundSettings) getTargetFragment();
            if (soundSettings.isAdded()) {
                soundSettings.enableWorkSync();
            }
    void enableWorkSync() {
        if (mWorkSoundController != null) {
            mWorkSoundController.enableWorkSync();
        }
    }
}
+319 −0

File added.

Preview size limit exceeded, changes collapsed.

+157 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.notification;

import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.TwoStatePreference;
import android.telephony.TelephonyManager;

import com.android.settings.DefaultRingtonePreference;
import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class WorkSoundPreferenceControllerTest {

    private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
    private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
    private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
    private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone";
    private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone";

    @Mock
    private Context mContext;
    @Mock
    private PreferenceScreen mScreen;
    @Mock
    private TelephonyManager mTelephonyManager;
    @Mock
    private AudioHelper mAudioHelper;
    @Mock
    private SoundSettings mFragment;

    private WorkSoundPreferenceController mController;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
        mController = new WorkSoundPreferenceController(mContext, mFragment, null, mAudioHelper);
    }

    @Test
    public void isAvailable_managedProfileAndNotSingleVolume_shouldReturnTrue() {
        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
                .thenReturn(UserHandle.myUserId());
        when(mAudioHelper.isSingleVolume()).thenReturn(false);

        assertThat(mController.isAvailable()).isTrue();
    }

    @Test
    public void isAvailable_noManagedProfile_shouldReturnFalse() {
        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
                .thenReturn(UserHandle.USER_NULL);
        when(mAudioHelper.isSingleVolume()).thenReturn(false);

        assertThat(mController.isAvailable()).isFalse();
    }

    @Test
    public void isAvailable_singleVolume_shouldReturnFalse() {
        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
                .thenReturn(UserHandle.myUserId());
        when(mAudioHelper.isSingleVolume()).thenReturn(true);

        assertThat(mController.isAvailable()).isFalse();
    }

    @Test
    public void onResume_available_shouldAddPreferenceCategory() {
        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
                .thenReturn(UserHandle.myUserId());
        when(mAudioHelper.isSingleVolume()).thenReturn(false);
        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
        when(mScreen.findPreference(KEY_WORK_CATEGORY))
            .thenReturn(mock(PreferenceGroup.class));
        when(mScreen.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS))
            .thenReturn(mock(TwoStatePreference.class));
        when(mScreen.findPreference(KEY_WORK_PHONE_RINGTONE))
            .thenReturn(mock(DefaultRingtonePreference.class));
        when(mScreen.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
            .thenReturn(mock(DefaultRingtonePreference.class));
        when(mScreen.findPreference(KEY_WORK_ALARM_RINGTONE))
            .thenReturn(mock(DefaultRingtonePreference.class));
        when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext);

        mController.onResume();

        verify(mFragment).addPreferencesFromResource(R.xml.sound_work_settings);
    }

    @Test
    public void onResume_notAvailable_shouldNotAddPreferenceCategory() {
        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
            .thenReturn(UserHandle.USER_NULL);
        when(mAudioHelper.isSingleVolume()).thenReturn(true);
        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);

        mController.onResume();

        verify(mFragment, never()).addPreferencesFromResource(anyInt());
    }

    @Test
    public void onPreferenceChange_shouldUpdateSummary() {
        final Preference preference = mock(Preference.class);
        when(preference.getKey()).thenReturn(KEY_WORK_PHONE_RINGTONE);

        mController.onPreferenceChange(preference, "hello");

        verify(preference).setSummary(anyString());
    }

}