blob: ab52c4abf3cab2cddfda010421839f5da1e4f343 [file] [log] [blame]
/*
* 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.internal.telephony;
import android.app.PendingIntent;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import com.android.internal.telephony.util.NotificationChannelController;
/**
* This contains Carrier specific logic based on the states/events
* managed in ServiceStateTracker.
* {@hide}
*/
public class CarrierServiceStateTracker extends Handler {
private static final String LOG_TAG = "CSST";
protected static final int CARRIER_EVENT_BASE = 100;
protected static final int CARRIER_EVENT_VOICE_REGISTRATION = CARRIER_EVENT_BASE + 1;
protected static final int CARRIER_EVENT_VOICE_DEREGISTRATION = CARRIER_EVENT_BASE + 2;
protected static final int CARRIER_EVENT_DATA_REGISTRATION = CARRIER_EVENT_BASE + 3;
protected static final int CARRIER_EVENT_DATA_DEREGISTRATION = CARRIER_EVENT_BASE + 4;
private static final int SHOW_NOTIFICATION = 200;
private static final int NOTIFICATION_ID = 1000;
private static final int UNINITIALIZED_DELAY_VALUE = -1;
private int mDelay = UNINITIALIZED_DELAY_VALUE;
private Phone mPhone;
private boolean mIsPhoneRegistered = false;
private ServiceStateTracker mSST;
public CarrierServiceStateTracker(Phone phone, ServiceStateTracker sst) {
this.mPhone = phone;
this.mSST = sst;
phone.getContext().registerReceiver(mBroadcastReceiver, new IntentFilter(
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CARRIER_EVENT_VOICE_REGISTRATION:
case CARRIER_EVENT_DATA_REGISTRATION:
mIsPhoneRegistered = true;
handleConfigChanges();
break;
case CARRIER_EVENT_VOICE_DEREGISTRATION:
case CARRIER_EVENT_DATA_DEREGISTRATION:
if (isGlobalModeOrRadioOffOrAirplaneMode()) {
break;
}
mIsPhoneRegistered = false;
handleConfigChanges();
break;
case SHOW_NOTIFICATION:
sendNotification();
break;
}
}
/**
* Returns true if the preferred network is set to 'Global' or the radio is off or in
* Airplane Mode else returns false.
*/
private boolean isGlobalModeOrRadioOffOrAirplaneMode() {
Context context = mPhone.getContext();
int preferredNetworkSetting = -1;
int airplaneMode = -1;
int subId = mPhone.getSubId();
try {
preferredNetworkSetting =
android.provider.Settings.Global.getInt(context.getContentResolver(),
android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId,
Phone.PREFERRED_NT_MODE);
airplaneMode = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0);
} catch (Exception e) {
Rlog.e(LOG_TAG, "Unable to get PREFERRED_NETWORK_MODE.");
return true;
}
return ((preferredNetworkSetting == RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) ||
!mSST.isRadioOn() || (airplaneMode != 0));
}
/**
* Contains logic to decide when to create/cancel notifications.
*/
private void handleConfigChanges() {
if (mDelay == UNINITIALIZED_DELAY_VALUE) {
cancelNotification();
return;
}
// send a notification if the device is registerd to a network.
if (mIsPhoneRegistered) {
cancelNotification();
Rlog.i(LOG_TAG, "canceling all notifications. ");
} else {
Message notificationMsg;
notificationMsg = obtainMessage(SHOW_NOTIFICATION, null);
Rlog.i(LOG_TAG, "starting timer for notifications. ");
sendMessageDelayed(notificationMsg, mDelay);
}
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
PersistableBundle b = carrierConfigManager.getConfigForSubId(mPhone.getSubId());
mDelay = b.getInt(CarrierConfigManager.KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT);
Rlog.i(LOG_TAG, "reading time to delay notification: " + mDelay);
handleConfigChanges();
}
};
/**
* Post a notification to the NotificationManager for changing network type.
*/
private void sendNotification() {
Context context = mPhone.getContext();
Rlog.i(LOG_TAG, "w/values: " + "," + mIsPhoneRegistered + "," + mDelay
+ "," + isGlobalModeOrRadioOffOrAirplaneMode() + "," + mSST.isRadioOn());
// exit if the network preference is set to Global or if the phone is registered.
if (isGlobalModeOrRadioOffOrAirplaneMode() || mIsPhoneRegistered) {
return;
}
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS);
PendingIntent settingsIntent = PendingIntent.getActivity(context, 0, notificationIntent,
PendingIntent.FLAG_ONE_SHOT);
CharSequence title =
context.getText(com.android.internal.R.string.NetworkPreferenceSwitchTitle);
CharSequence details =
context.getText(com.android.internal.R.string.NetworkPreferenceSwitchSummary);
Notification mNotification = new Notification.Builder(context)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
.setContentTitle(title)
.setColor(context.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color))
.setStyle(new Notification.BigTextStyle().bigText(details))
.setContentText(details)
.setContentIntent(settingsIntent)
.setChannel(NotificationChannelController.CHANNEL_ID_ALERT)
.build();
notificationManager.notify(NOTIFICATION_ID, mNotification);
}
/**
* Cancel notifications if a registration is pending or has been sent.
*/
private void cancelNotification() {
Context context = mPhone.getContext();
mIsPhoneRegistered = true;
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
}