16a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux/*
26a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * Copyright (C) 2015 The Android Open Source Project
36a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux *
46a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * Licensed under the Apache License, Version 2.0 (the "License");
56a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * you may not use this file except in compliance with the License.
66a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * You may obtain a copy of the License at
76a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux *
86a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux *      http://www.apache.org/licenses/LICENSE-2.0
96a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux *
106a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * Unless required by applicable law or agreed to in writing, software
116a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * distributed under the License is distributed on an "AS IS" BASIS,
126a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * See the License for the specific language governing permissions and
146a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * limitations under the License.
156a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux */
166a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
176a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuxpackage com.android.deskclock.data;
186a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
196a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.content.ContentResolver;
206a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.content.Context;
216a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.database.ContentObserver;
226a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.media.Ringtone;
236a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.media.RingtoneManager;
246a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.net.Uri;
256a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.os.Handler;
266a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.provider.Settings;
276a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport android.util.ArrayMap;
286a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
296a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport com.android.deskclock.LogUtils;
306a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport com.android.deskclock.R;
316a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport com.android.deskclock.provider.Alarm;
326a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
336a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuximport java.util.Map;
346a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
356a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux/**
366a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux * All alarm data will eventually be accessed via this model.
376a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux */
386a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieuxfinal class AlarmModel {
396a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
406a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    private final Context mContext;
416a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
426a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    /** The model from which settings are fetched. */
436a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    private final SettingsModel mSettingsModel;
446a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
456a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    /** The uri of the default ringtone to play for new alarms; mirrors last selection. */
466a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    private Uri mDefaultAlarmRingtoneUri;
476a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
486a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    /** Maps ringtone uri to ringtone title; looking up a title from scratch is expensive. */
496a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    private final Map<Uri, String> mRingtoneTitles = new ArrayMap<>(8);
506a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
516a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    AlarmModel(Context context, SettingsModel settingsModel) {
526a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        mContext = context;
536a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        mSettingsModel = settingsModel;
546a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
556a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        // Clear caches affected by system settings when system settings change.
566a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        final ContentResolver cr = mContext.getContentResolver();
576a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        final ContentObserver observer = new SystemAlarmAlertChangeObserver();
586a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        cr.registerContentObserver(Settings.System.DEFAULT_ALARM_ALERT_URI, false, observer);
596a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    }
606a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
616a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    Uri getDefaultAlarmRingtoneUri() {
626a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        if (mDefaultAlarmRingtoneUri == null) {
636a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            mDefaultAlarmRingtoneUri = mSettingsModel.getDefaultAlarmRingtoneUri();
646a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        }
656a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
666a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        return mDefaultAlarmRingtoneUri;
676a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    }
686a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
696a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    void setDefaultAlarmRingtoneUri(Uri uri) {
706a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        mSettingsModel.setDefaultAlarmRingtoneUri(uri);
716a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        mDefaultAlarmRingtoneUri = uri;
726a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    }
736a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
746a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    String getAlarmRingtoneTitle(Uri uri) {
756a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        // Special case: no ringtone has a title of "Silent".
766a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        if (Alarm.NO_RINGTONE_URI.equals(uri)) {
776a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            return mContext.getString(R.string.silent_ringtone_title);
786a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        }
796a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
806a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        // Check the cache.
816a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        String title = mRingtoneTitles.get(uri);
826a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
836a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        if (title == null) {
846a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            // This is slow because a media player is created during Ringtone object creation.
856a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            final Ringtone ringtone = RingtoneManager.getRingtone(mContext, uri);
866a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            if (ringtone == null) {
876a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux                LogUtils.e("No ringtone for uri: %s", uri);
886a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux                return mContext.getString(R.string.unknown_ringtone_title);
896a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            }
906a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
916a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            // Cache the title for later use.
926a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            title = ringtone.getTitle(mContext);
936a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            mRingtoneTitles.put(uri, title);
946a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        }
956a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        return title;
966a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    }
976a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
986a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    /**
996a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux     * This receiver is notified when system settings change. Cached information built on
1006a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux     * those system settings must be cleared.
1016a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux     */
1026a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    private final class SystemAlarmAlertChangeObserver extends ContentObserver {
1036a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
1046a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        private SystemAlarmAlertChangeObserver() {
1056a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            super(new Handler());
1066a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        }
1076a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
1086a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        @Override
1096a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        public void onChange(boolean selfChange) {
1106a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            super.onChange(selfChange);
1116a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
1126a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            LogUtils.i("Detected change to system default alarm ringtone; clearing caches");
1136a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
1146a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            mDefaultAlarmRingtoneUri = null;
1156a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux
1166a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            // Titles such as "Default ringtone (Oxygen)" are wrong after default ringtone changes.
1176a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux            mRingtoneTitles.clear();
1186a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux        }
1196a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux    }
1206a59a7b2c034557bc8bc7481544db5cd1105a891James Lemieux}