1/*
2 * Copyright (C) 2017 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 */
16package com.android.internal.telephony.util;
17
18import android.app.NotificationChannel;
19import android.app.NotificationManager;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.media.AudioAttributes;
25import android.net.Uri;
26import android.provider.Settings;
27import android.telephony.SubscriptionManager;
28
29import com.android.internal.R;
30
31import java.util.Arrays;
32
33
34public class NotificationChannelController {
35
36    /**
37     * list of {@link android.app.NotificationChannel} for telephony service.
38     */
39    public static final String CHANNEL_ID_ALERT = "alert";
40    public static final String CHANNEL_ID_CALL_FORWARD = "callForward";
41    public static final String CHANNEL_ID_MOBILE_DATA_STATUS = "mobileDataAlertNew";
42    public static final String CHANNEL_ID_SMS = "sms";
43    public static final String CHANNEL_ID_VOICE_MAIL = "voiceMail";
44    public static final String CHANNEL_ID_WFC = "wfc";
45
46    /** deprecated channel, replaced with @see #CHANNEL_ID_MOBILE_DATA_STATUS */
47    private static final String CHANNEL_ID_MOBILE_DATA_ALERT_DEPRECATED = "mobileDataAlert";
48
49    /**
50     * Creates all notification channels and registers with NotificationManager. If a channel
51     * with the same ID is already registered, NotificationManager will ignore this call.
52     */
53    private static void createAll(Context context) {
54        final NotificationChannel alertChannel = new NotificationChannel(
55                CHANNEL_ID_ALERT,
56                context.getText(R.string.notification_channel_network_alert),
57                NotificationManager.IMPORTANCE_DEFAULT);
58        alertChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
59                new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build());
60
61        final NotificationChannel mobileDataStatusChannel = new NotificationChannel(
62                CHANNEL_ID_MOBILE_DATA_STATUS,
63                context.getText(R.string.notification_channel_mobile_data_status),
64                NotificationManager.IMPORTANCE_LOW);
65        // allow users to block notifications from system
66        mobileDataStatusChannel.setBlockableSystem(true);
67
68        context.getSystemService(NotificationManager.class)
69                .createNotificationChannels(Arrays.asList(
70                new NotificationChannel(CHANNEL_ID_CALL_FORWARD,
71                        context.getText(R.string.notification_channel_call_forward),
72                        NotificationManager.IMPORTANCE_LOW),
73                new NotificationChannel(CHANNEL_ID_SMS,
74                        context.getText(R.string.notification_channel_sms),
75                        NotificationManager.IMPORTANCE_HIGH),
76                new NotificationChannel(CHANNEL_ID_WFC,
77                        context.getText(R.string.notification_channel_wfc),
78                        NotificationManager.IMPORTANCE_LOW),
79                alertChannel,
80                mobileDataStatusChannel));
81        // only for update
82        if (getChannel(CHANNEL_ID_VOICE_MAIL, context) != null) {
83            migrateVoicemailNotificationSettings(context);
84        }
85        // after channel has been created there is no way to change the channel setting
86        // programmatically. delete the old channel and create a new one with a new ID.
87        if (getChannel(CHANNEL_ID_MOBILE_DATA_ALERT_DEPRECATED, context) != null) {
88            context.getSystemService(NotificationManager.class)
89                    .deleteNotificationChannel(CHANNEL_ID_MOBILE_DATA_ALERT_DEPRECATED);
90        }
91    }
92
93    public NotificationChannelController(Context context) {
94        IntentFilter intentFilter = new IntentFilter();
95        intentFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
96        intentFilter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
97        context.registerReceiver(mBroadcastReceiver, intentFilter);
98        createAll(context);
99    }
100
101    public static NotificationChannel getChannel(String channelId, Context context) {
102        return context.getSystemService(NotificationManager.class)
103                .getNotificationChannel(channelId);
104    }
105
106    /**
107     * migrate deprecated voicemail notification settings to initial notification channel settings
108     * {@link VoicemailNotificationSettingsUtil#getRingTonePreference(Context)}}
109     * {@link VoicemailNotificationSettingsUtil#getVibrationPreference(Context)}
110     * notification settings are based on subId, only migrate if sub id matches.
111     * otherwise fallback to predefined voicemail channel settings.
112     * @param context
113     */
114    private static void migrateVoicemailNotificationSettings(Context context) {
115        final NotificationChannel voiceMailChannel = new NotificationChannel(
116                CHANNEL_ID_VOICE_MAIL,
117                context.getText(R.string.notification_channel_voice_mail),
118                NotificationManager.IMPORTANCE_DEFAULT);
119        voiceMailChannel.enableVibration(
120                VoicemailNotificationSettingsUtil.getVibrationPreference(context));
121        Uri sound = VoicemailNotificationSettingsUtil.getRingTonePreference(context);
122        voiceMailChannel.setSound(
123                (sound == null) ? Settings.System.DEFAULT_NOTIFICATION_URI : sound,
124                new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build());
125        context.getSystemService(NotificationManager.class)
126                .createNotificationChannel(voiceMailChannel);
127    }
128
129    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
130        @Override
131        public void onReceive(Context context, Intent intent) {
132            if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
133                // rename all notification channels on locale change
134                createAll(context);
135            } else if (Intent.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
136                // migrate voicemail notification settings on sim load
137                if (SubscriptionManager.INVALID_SUBSCRIPTION_ID !=
138                        SubscriptionManager.getDefaultSubscriptionId()) {
139                    migrateVoicemailNotificationSettings(context);
140                }
141            }
142        }
143    };
144}
145