blob: 3ffc7fc043ca49985f5d2d9980212a3033b8ca66 [file] [log] [blame]
package com.android.clockwork.cellular;
import static com.android.clockwork.cellular.WearCellularMediator.CELL_AUTO_OFF;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.google.android.clockwork.signaldetector.SignalDetectorSettings;
import java.util.concurrent.TimeUnit;
public class WearCellularMediatorSettings implements SignalDetectorSettings {
private static final String MOBILE_SIGNAL_DETECTOR_SERVICE_ALLOWED_KEY =
"mobile_signal_detector_service_allowed";
private static final int MOBILE_SIGNAL_DETECTOR_SERVICE_ALLOWED_DEFAULT = 1 /* true*/;
private static final String MOBILE_SIGNAL_DETECTOR_QUEUE_MAX_SIZE_KEY =
"mobile_signal_detector_queue_max_size";
private static final int MOBILE_SIGNAL_DETECTOR_QUEUE_MAX_SIZE_DEFAULT = 50;
private static final String MOBILE_SIGNAL_DETECTOR_INTERVAL_MS_KEY =
"mobile_signal_detector_interval_ms";
private static final long MOBILE_SIGNAL_DETECTOR_INTERVAL_MS_DEFAULT =
TimeUnit.MINUTES.toMillis(12);
private static final String MOBILE_SIGNAL_DETECTOR_BATTERY_DROP_THRESHOLD_KEY =
"mobile_signal_detector_battery_drop_threshold";
private static final int MOBILE_SIGNAL_DETECTOR_BATTERY_DROP_THRESHOLD_DEFAULT = 2;
private static final String MOBILE_SIGNAL_DETECTOR_FREQUENT_EVENT_NUM_KEY =
"mobile_signal_detector_frequent_event_num";
private static final int MOBILE_SIGNAL_DETECTOR_FREQUENT_EVENT_NUM_DEFAULT = 20;
private static final String MOBILE_SIGNAL_DETECTOR_DISABLED_MCC_MNC_LIST_KEY =
"mobile_signal_detector_disabled_mcc_mnc_list";
private static final String MOBILE_SIGNAL_DETECTOR_DISABLED_MCC_MNC_LIST_DEFAULT = "";
public static final Uri MOBILE_SIGNAL_DETECTOR_DISABLED_MCC_MNC_LIST_KEY_URI =
Settings.Global.getUriFor(MOBILE_SIGNAL_DETECTOR_DISABLED_MCC_MNC_LIST_KEY);
private static final String CELLULAR_OFF_DURING_POWER_SAVE_KEY =
"cellular_mediator_off_during_power_save";
private static final int CELLULAR_OFF_DURING_POWER_SAVE_DEFAULT = 1 /* true */;
private static final String PRODUCT_NAME = "ro.product.name";
private static final String CARRIER_NAME = "ro.carrier";
private static final String VERIZON_SUFFIX = "_vz";
private static final String VERIZON_NAME = "verizon";
private final Context mContext;
private final String mSimOperator;
private final boolean mCellAutoEnabled;
/**
* @param context the application context.
* @param simOperator the sim operator currently in use for the device.
*/
public WearCellularMediatorSettings(Context context, String simOperator) {
mContext = context;
mSimOperator = simOperator;
mCellAutoEnabled =
SystemProperties.getBoolean("config.enable_cellmediator_cell_auto", false);
}
/**
* Get the value of Settings.System.CELL_AUTO_SETTING_KEY.
*/
public int getCellAutoSetting() {
return mCellAutoEnabled ?
Settings.System.getInt(
mContext.getContentResolver(),
WearCellularMediator.CELL_AUTO_SETTING_KEY,
WearCellularMediator.CELL_AUTO_SETTING_DEFAULT)
: CELL_AUTO_OFF;
}
/**
* Get the value of Settings.Global.CELL_ON.
* The default value is CELL_ON_FLAG if not defined because we assume this service only runs on
* the cellular-capable device (behind the config.enable_cellmediator flag in SystemServer).
*/
public int getCellState() {
return Settings.Global.getInt(
mContext.getContentResolver(),
Settings.Global.CELL_ON,
PhoneConstants.CELL_ON_FLAG);
}
@Override
public boolean getMobileSignalDetectorAllowed() {
// Use the developer options override, if possible.
Cursor cursor = mContext.getContentResolver()
.query(WearCellularConstants.MOBILE_SIGNAL_DETECTOR_URI, null, null, null, null);
if (cursor != null) {
try {
while (cursor.moveToNext()) {
if (WearCellularConstants.KEY_MOBILE_SIGNAL_DETECTOR.equals(
cursor.getString(0))) {
return Boolean.parseBoolean(cursor.getString(1));
}
}
} finally {
cursor.close();
}
}
boolean signalDetectorAllowedKeyValue =
Settings.Global.getInt(mContext.getContentResolver(),
MOBILE_SIGNAL_DETECTOR_SERVICE_ALLOWED_KEY,
MOBILE_SIGNAL_DETECTOR_SERVICE_ALLOWED_DEFAULT) == 1;
return !shouldDisableForCurrentOperator() && signalDetectorAllowedKeyValue;
}
@Override
public int getMobileSignalDetectorQueueMaxSize() {
return Settings.Global.getInt(
mContext.getContentResolver(),
MOBILE_SIGNAL_DETECTOR_QUEUE_MAX_SIZE_KEY,
MOBILE_SIGNAL_DETECTOR_QUEUE_MAX_SIZE_DEFAULT);
}
@Override
public long getMobileSignalDetectorIntervalMs() {
return Settings.Global.getLong(
mContext.getContentResolver(),
MOBILE_SIGNAL_DETECTOR_INTERVAL_MS_KEY,
MOBILE_SIGNAL_DETECTOR_INTERVAL_MS_DEFAULT);
}
@Override
public int getMobileSignalDetectorBatteryDropThreshold() {
return Settings.Global.getInt(
mContext.getContentResolver(),
MOBILE_SIGNAL_DETECTOR_BATTERY_DROP_THRESHOLD_KEY,
MOBILE_SIGNAL_DETECTOR_BATTERY_DROP_THRESHOLD_DEFAULT);
}
@Override
public int getMobileSignalDetectorFrequentEventNum() {
return Settings.Global.getInt(
mContext.getContentResolver(),
MOBILE_SIGNAL_DETECTOR_FREQUENT_EVENT_NUM_KEY,
MOBILE_SIGNAL_DETECTOR_FREQUENT_EVENT_NUM_DEFAULT);
}
@Override
public boolean isDebugMode() {
return false;
}
/**
* Do not disable cell in power save mode for Verizon.
* More details in b/34507932.
*/
public boolean shouldTurnCellularOffDuringPowerSave() {
int cellularDuringPowerSaveSetting =
Settings.Global.getInt(
mContext.getContentResolver(),
CELLULAR_OFF_DURING_POWER_SAVE_KEY,
CELLULAR_OFF_DURING_POWER_SAVE_DEFAULT);
String productName = SystemProperties.get(PRODUCT_NAME);
boolean isVerizon =
(productName != null && productName.endsWith(VERIZON_SUFFIX))
|| TextUtils.equals(VERIZON_NAME, SystemProperties.get(CARRIER_NAME));
return cellularDuringPowerSaveSetting == 1 && !isVerizon;
}
private boolean shouldDisableForCurrentOperator() {
String disabledMccMncList = Settings.Global.getString(mContext.getContentResolver(),
MOBILE_SIGNAL_DETECTOR_DISABLED_MCC_MNC_LIST_KEY);
if (disabledMccMncList == null || TextUtils.isEmpty(mSimOperator)) {
return false;
}
String[] list = disabledMccMncList.split(",");
for (String disabled : list) {
if (mSimOperator.equals(disabled)) {
return true;
}
}
return false;
}
/**
* For some edge cases (b/35588911), radio power can be turned on inadvertently and
* the variable to track radio power state doesn't get updated.
* Note TelephonyManager.isRadioOn() is not used because in cases like b/35588911, it uses
* the wrong default subscription id.
*
* @return RADIO_ON_STATE_UNKNOWN, RADIO_ON_STATE_ON, or RADIO_ON_STATE_OFF.
*/
public int getRadioOnState() {
// The trick to get subId is used in TelephonyManager#getSimOperatorNumeric().
int subId = SubscriptionManager.getDefaultDataSubscriptionId();
if (!SubscriptionManager.isUsableSubIdValue(subId)) {
subId = SubscriptionManager.getDefaultSmsSubscriptionId();
if (!SubscriptionManager.isUsableSubIdValue(subId)) {
subId = SubscriptionManager.getDefaultVoiceSubscriptionId();
if (!SubscriptionManager.isUsableSubIdValue(subId)) {
subId = SubscriptionManager.getDefaultSubscriptionId();
}
}
}
if (!SubscriptionManager.isUsableSubIdValue(subId)) {
return WearCellularMediator.RADIO_ON_STATE_UNKNOWN;
}
try {
ITelephony telephony = ITelephony.Stub.asInterface(ServiceManager.getService(
Context.TELEPHONY_SERVICE));
if (telephony != null) {
boolean isRadioOn = telephony.isRadioOnForSubscriber(subId,
mContext.getOpPackageName());
return isRadioOn ? WearCellularMediator.RADIO_ON_STATE_ON
: WearCellularMediator.RADIO_ON_STATE_OFF;
}
} catch (RemoteException e) {
Log.e(WearCellularMediator.TAG, "RemoteException calling isRadioOnForSubscriber()", e);
}
return WearCellularMediator.RADIO_ON_STATE_UNKNOWN;
}
}