• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.notification;
18 
19 import android.annotation.UserIdInt;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.app.FragmentManager;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.media.Ringtone;
29 import android.media.RingtoneManager;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.provider.Settings;
35 import android.support.v7.preference.Preference;
36 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
37 import android.support.v7.preference.PreferenceGroup;
38 import android.support.v7.preference.PreferenceScreen;
39 import android.support.v7.preference.TwoStatePreference;
40 
41 import com.android.internal.annotations.VisibleForTesting;
42 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
43 import com.android.settings.DefaultRingtonePreference;
44 import com.android.settings.R;
45 import com.android.settings.Utils;
46 import com.android.settings.core.PreferenceController;
47 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
48 import com.android.settings.core.lifecycle.Lifecycle;
49 import com.android.settings.core.lifecycle.LifecycleObserver;
50 import com.android.settings.core.lifecycle.events.OnPause;
51 import com.android.settings.core.lifecycle.events.OnResume;
52 
53 public class WorkSoundPreferenceController extends PreferenceController implements
54         OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
55 
56     private static final String TAG = "WorkSoundPrefController";
57     private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
58     private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds";
59     private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone";
60     private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone";
61     private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone";
62 
63     private final boolean mVoiceCapable;
64     private final UserManager mUserManager;
65     private final SoundSettings mParent;
66     private final AudioHelper mHelper;
67 
68     private PreferenceGroup mWorkPreferenceCategory;
69     private TwoStatePreference mWorkUsePersonalSounds;
70     private Preference mWorkPhoneRingtonePreference;
71     private Preference mWorkNotificationRingtonePreference;
72     private Preference mWorkAlarmRingtonePreference;
73 
74     @UserIdInt
75     private int mManagedProfileId;
76 
WorkSoundPreferenceController(Context context, SoundSettings parent, Lifecycle lifecycle)77     public WorkSoundPreferenceController(Context context, SoundSettings parent,
78             Lifecycle lifecycle) {
79         this(context, parent, lifecycle, new AudioHelper(context));
80     }
81 
82     @VisibleForTesting
WorkSoundPreferenceController(Context context, SoundSettings parent, Lifecycle lifecycle, AudioHelper helper)83     WorkSoundPreferenceController(Context context, SoundSettings parent, Lifecycle lifecycle,
84             AudioHelper helper) {
85         super(context);
86         mUserManager = UserManager.get(context);
87         mVoiceCapable = Utils.isVoiceCapable(mContext);
88         mParent = parent;
89         mHelper = helper;
90         if (lifecycle != null) {
91             lifecycle.addObserver(this);
92         }
93     }
94 
95     @Override
displayPreference(PreferenceScreen screen)96     public void displayPreference(PreferenceScreen screen) {
97         mWorkPreferenceCategory = (PreferenceGroup) screen.findPreference(KEY_WORK_CATEGORY);
98         if (mWorkPreferenceCategory != null) {
99             mWorkPreferenceCategory.setVisible(isAvailable());
100         }
101     }
102 
103     @Override
onResume()104     public void onResume() {
105         IntentFilter managedProfileFilter = new IntentFilter();
106         managedProfileFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
107         managedProfileFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
108         mContext.registerReceiver(mManagedProfileReceiver, managedProfileFilter);
109 
110         mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
111         updateWorkPreferences();
112     }
113 
114     @Override
onPause()115     public void onPause() {
116         mContext.unregisterReceiver(mManagedProfileReceiver);
117     }
118 
119     @Override
getPreferenceKey()120     public String getPreferenceKey() {
121         return KEY_WORK_CATEGORY;
122     }
123 
124     @Override
isAvailable()125     public boolean isAvailable() {
126         return mHelper.getManagedProfileId(mUserManager) != UserHandle.USER_NULL
127                 && shouldShowRingtoneSettings();
128     }
129 
130     @Override
handlePreferenceTreeClick(Preference preference)131     public boolean handlePreferenceTreeClick(Preference preference) {
132         return false;
133     }
134 
135     /**
136      * Updates the summary of work preferences
137      *
138      * This controller listens to changes on the work ringtone preferences, identified by keys
139      * "work_ringtone", "work_notification_ringtone" and "work_alarm_ringtone".
140      */
141     @Override
onPreferenceChange(Preference preference, Object newValue)142     public boolean onPreferenceChange(Preference preference, Object newValue) {
143         int ringtoneType;
144         if (KEY_WORK_PHONE_RINGTONE.equals(preference.getKey())) {
145             ringtoneType = RingtoneManager.TYPE_RINGTONE;
146         } else if (KEY_WORK_NOTIFICATION_RINGTONE.equals(preference.getKey())) {
147             ringtoneType = RingtoneManager.TYPE_NOTIFICATION;
148         } else if (KEY_WORK_ALARM_RINGTONE.equals(preference.getKey())) {
149             ringtoneType = RingtoneManager.TYPE_ALARM;
150         } else {
151             return true;
152         }
153 
154         preference.setSummary(updateRingtoneName(getManagedProfileContext(), ringtoneType));
155         return true;
156     }
157 
158     // === Phone & notification ringtone ===
159 
shouldShowRingtoneSettings()160     private boolean shouldShowRingtoneSettings() {
161         return !mHelper.isSingleVolume();
162     }
163 
updateRingtoneName(Context context, int type)164     private CharSequence updateRingtoneName(Context context, int type) {
165         if (context == null || !mHelper.isUserUnlocked(mUserManager, context.getUserId())) {
166             return mContext.getString(R.string.managed_profile_not_available_label);
167         }
168         Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
169         return Ringtone.getTitle(context, ringtoneUri, false /* followSettingsUri */,
170                 true /* allowRemote */);
171     }
172 
getManagedProfileContext()173     private Context getManagedProfileContext() {
174         if (mManagedProfileId == UserHandle.USER_NULL) {
175             return null;
176         }
177         return mHelper.createPackageContextAsUser(mManagedProfileId);
178     }
179 
initWorkPreference(PreferenceGroup root, String key)180     private DefaultRingtonePreference initWorkPreference(PreferenceGroup root, String key) {
181         DefaultRingtonePreference pref =
182                 (DefaultRingtonePreference) root.findPreference(key);
183         pref.setOnPreferenceChangeListener(this);
184 
185         // Required so that RingtonePickerActivity lists the work profile ringtones
186         pref.setUserId(mManagedProfileId);
187         return pref;
188     }
189 
updateWorkPreferences()190     private void updateWorkPreferences() {
191         if (mWorkPreferenceCategory == null) {
192             return;
193         }
194         final boolean isAvailable = isAvailable();
195         mWorkPreferenceCategory.setVisible(isAvailable);
196         if (!isAvailable) {
197             return;
198         }
199         if (mWorkUsePersonalSounds == null) {
200             mWorkUsePersonalSounds = (TwoStatePreference)
201                     mWorkPreferenceCategory.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS);
202             mWorkUsePersonalSounds.setOnPreferenceChangeListener((Preference p, Object value) -> {
203                 if ((boolean) value) {
204                     UnifyWorkDialogFragment.show(mParent);
205                     return false;
206                 } else {
207                     disableWorkSync();
208                     return true;
209                 }
210             });
211         }
212         if (mWorkPhoneRingtonePreference == null) {
213             mWorkPhoneRingtonePreference = initWorkPreference(mWorkPreferenceCategory,
214                     KEY_WORK_PHONE_RINGTONE);
215         }
216         if (mWorkNotificationRingtonePreference == null) {
217             mWorkNotificationRingtonePreference = initWorkPreference(mWorkPreferenceCategory,
218                     KEY_WORK_NOTIFICATION_RINGTONE);
219         }
220         if (mWorkAlarmRingtonePreference == null) {
221             mWorkAlarmRingtonePreference = initWorkPreference(mWorkPreferenceCategory,
222                     KEY_WORK_ALARM_RINGTONE);
223         }
224         if (!mVoiceCapable) {
225             mWorkPhoneRingtonePreference.setVisible(false);
226             mWorkPhoneRingtonePreference = null;
227         }
228 
229         final Context managedProfileContext = getManagedProfileContext();
230         if (Settings.Secure.getIntForUser(managedProfileContext.getContentResolver(),
231                 Settings.Secure.SYNC_PARENT_SOUNDS, 0, mManagedProfileId) == 1) {
232             enableWorkSyncSettings();
233         } else {
234             disableWorkSyncSettings();
235         }
236     }
237 
enableWorkSync()238     void enableWorkSync() {
239         RingtoneManager.enableSyncFromParent(getManagedProfileContext());
240         enableWorkSyncSettings();
241     }
242 
enableWorkSyncSettings()243     private void enableWorkSyncSettings() {
244         mWorkUsePersonalSounds.setChecked(true);
245 
246         if (mWorkPhoneRingtonePreference != null) {
247             mWorkPhoneRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
248         }
249         mWorkNotificationRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
250         mWorkAlarmRingtonePreference.setSummary(R.string.work_sound_same_as_personal);
251     }
252 
disableWorkSync()253     private void disableWorkSync() {
254         RingtoneManager.disableSyncFromParent(getManagedProfileContext());
255         disableWorkSyncSettings();
256     }
257 
disableWorkSyncSettings()258     private void disableWorkSyncSettings() {
259         if (mWorkPhoneRingtonePreference != null) {
260             mWorkPhoneRingtonePreference.setEnabled(true);
261         }
262         mWorkNotificationRingtonePreference.setEnabled(true);
263         mWorkAlarmRingtonePreference.setEnabled(true);
264 
265         updateWorkRingtoneSummaries();
266     }
267 
updateWorkRingtoneSummaries()268     private void updateWorkRingtoneSummaries() {
269         Context managedProfileContext = getManagedProfileContext();
270 
271         if (mWorkPhoneRingtonePreference != null) {
272             mWorkPhoneRingtonePreference.setSummary(
273                     updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_RINGTONE));
274         }
275         mWorkNotificationRingtonePreference.setSummary(
276                 updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_NOTIFICATION));
277         mWorkAlarmRingtonePreference.setSummary(
278                 updateRingtoneName(managedProfileContext, RingtoneManager.TYPE_ALARM));
279     }
280 
onManagedProfileAdded(@serIdInt int profileId)281     public void onManagedProfileAdded(@UserIdInt int profileId) {
282         if (mManagedProfileId == UserHandle.USER_NULL) {
283             mManagedProfileId = profileId;
284             updateWorkPreferences();
285         }
286     }
287 
onManagedProfileRemoved(@serIdInt int profileId)288     public void onManagedProfileRemoved(@UserIdInt int profileId) {
289         if (mManagedProfileId == profileId) {
290             mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
291             updateWorkPreferences();
292         }
293     }
294 
295     private final BroadcastReceiver mManagedProfileReceiver = new BroadcastReceiver() {
296         @Override
297         public void onReceive(Context context, Intent intent) {
298             final int userId = ((UserHandle) intent.getExtra(Intent.EXTRA_USER)).getIdentifier();
299             switch (intent.getAction()) {
300                 case Intent.ACTION_MANAGED_PROFILE_ADDED: {
301                     onManagedProfileAdded(userId);
302                     return;
303                 }
304                 case Intent.ACTION_MANAGED_PROFILE_REMOVED: {
305                     onManagedProfileRemoved(userId);
306                     return;
307                 }
308             }
309         }
310     };
311 
312     public static class UnifyWorkDialogFragment extends InstrumentedDialogFragment
313             implements DialogInterface.OnClickListener {
314         private static final String TAG = "UnifyWorkDialogFragment";
315         private static final int REQUEST_CODE = 200;
316 
317         @Override
getMetricsCategory()318         public int getMetricsCategory() {
319             return MetricsEvent.DIALOG_UNIFY_SOUND_SETTINGS;
320         }
321 
322         @Override
onCreateDialog(Bundle savedInstanceState)323         public Dialog onCreateDialog(Bundle savedInstanceState) {
324             return new AlertDialog.Builder(getActivity())
325                     .setTitle(R.string.work_sync_dialog_title)
326                     .setMessage(R.string.work_sync_dialog_message)
327                     .setPositiveButton(R.string.work_sync_dialog_yes, UnifyWorkDialogFragment.this)
328                     .setNegativeButton(android.R.string.no, null)
329                     .create();
330         }
331 
show(SoundSettings parent)332         public static void show(SoundSettings parent) {
333             FragmentManager fm = parent.getFragmentManager();
334             if (fm.findFragmentByTag(TAG) == null) {
335                 UnifyWorkDialogFragment fragment = new UnifyWorkDialogFragment();
336                 fragment.setTargetFragment(parent, REQUEST_CODE);
337                 fragment.show(fm, TAG);
338             }
339         }
340 
341         @Override
onClick(DialogInterface dialog, int which)342         public void onClick(DialogInterface dialog, int which) {
343             SoundSettings soundSettings = (SoundSettings) getTargetFragment();
344             if (soundSettings.isAdded()) {
345                 soundSettings.enableWorkSync();
346             }
347         }
348     }
349 
350 }
351