blob: 9e461580b24419907a82885cd4de3a2af053dbea [file] [log] [blame]
/*
* Copyright (C) 2018 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.settings.network.telephony;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsMmTelManager;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.network.ims.VolteQueryImsState;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SliceBroadcastReceiver;
/**
* Helper class to control slices for enhanced 4g LTE settings.
*/
public class Enhanced4gLteSliceHelper {
private static final String TAG = "Enhanced4gLteSlice";
/**
* Action passed for changes to enhanced 4g LTE slice (toggle).
*/
public static final String ACTION_ENHANCED_4G_LTE_CHANGED =
"com.android.settings.mobilenetwork.action.ENHANCED_4G_LTE_CHANGED";
/**
* Action for mobile network settings activity which
* allows setting configuration for Enhanced 4G LTE
* related settings
*/
public static final String ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY =
"android.settings.NETWORK_OPERATOR_SETTINGS";
private final Context mContext;
/**
* Phone package name
*/
private static final String PACKAGE_PHONE = "com.android.phone";
/**
* String resource type
*/
private static final String RESOURCE_TYPE_STRING = "string";
/**
* Enhanced 4g lte mode title variant resource name
*/
private static final String RESOURCE_ENHANCED_4G_LTE_MODE_TITLE_VARIANT =
"enhanced_4g_lte_mode_title_variant";
@VisibleForTesting
public Enhanced4gLteSliceHelper(Context context) {
mContext = context;
}
/**
* Returns Slice object for enhanced_4g_lte settings.
*
* If enhanced 4g LTE is not supported for the current carrier, this method will return slice
* with not supported message.
*
* If enhanced 4g LTE is not editable for the current carrier, this method will return slice
* with not editable message.
*
* If enhanced 4g LTE setting can be changed, this method will return the slice to toggle
* enhanced 4g LTE option with ACTION_ENHANCED_4G_LTE_CHANGED as endItem.
*/
public Slice createEnhanced4gLteSlice(Uri sliceUri) {
final int subId = getDefaultVoiceSubId();
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
Log.d(TAG, "Invalid subscription Id");
return null;
}
if (isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL, subId, false)
|| !isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, subId,
true)) {
Log.d(TAG, "Setting is either hidden or not editable");
return null;
}
final VolteQueryImsState queryState = queryImsState(subId);
if (!queryState.isVoLteProvisioned()) {
Log.d(TAG, "Setting is either not provisioned or not enabled by Platform");
return null;
}
try {
return getEnhanced4gLteSlice(sliceUri,
queryState.isEnabledByUser(), subId);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Unable to read the current Enhanced 4g LTE status", e);
return null;
}
}
/**
* Builds a toggle slice where the intent takes you to the Enhanced 4G LTE page and the toggle
* enables/disables Enhanced 4G LTE mode setting.
*/
private Slice getEnhanced4gLteSlice(Uri sliceUri, boolean isEnhanced4gLteEnabled, int subId) {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_launcher_settings);
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder()
.setTitle(getEnhanced4glteModeTitle(subId))
.addEndItem(
SliceAction.createToggle(
getBroadcastIntent(ACTION_ENHANCED_4G_LTE_CHANGED),
null /* actionTitle */, isEnhanced4gLteEnabled))
.setPrimaryAction(
SliceAction.createDeeplink(
getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
icon,
ListBuilder.ICON_IMAGE,
getEnhanced4glteModeTitle(subId))))
.build();
}
/**
* Handles Enhanced 4G LTE mode setting change from Enhanced 4G LTE slice and posts
* notification. Should be called when intent action is ACTION_ENHANCED_4G_LTE_CHANGED
*
* @param intent action performed
*/
public void handleEnhanced4gLteChanged(Intent intent) {
// skip checking when no toggle state update contained within Intent
final boolean newValue = intent.getBooleanExtra(EXTRA_TOGGLE_STATE, false);
if (newValue != intent.getBooleanExtra(EXTRA_TOGGLE_STATE, true)) {
notifyEnhanced4gLteUpdate();
return;
}
final int subId = getDefaultVoiceSubId();
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
notifyEnhanced4gLteUpdate();
return;
}
final VolteQueryImsState queryState = queryImsState(subId);
final boolean currentValue = queryState.isEnabledByUser()
&& queryState.isAllowUserControl();
if (newValue == currentValue) {
notifyEnhanced4gLteUpdate();
return;
}
// isVoLteProvisioned() is the last item to check since it might block the main thread
if (queryState.isVoLteProvisioned()) {
setEnhanced4gLteModeSetting(subId, newValue);
}
notifyEnhanced4gLteUpdate();
}
private void notifyEnhanced4gLteUpdate() {
// notify change in slice in any case to get re-queried. This would result in displaying
// appropriate message with the updated setting.
mContext.getContentResolver().notifyChange(CustomSliceRegistry.ENHANCED_4G_SLICE_URI, null);
}
@VisibleForTesting
void setEnhanced4gLteModeSetting(int subId, boolean isEnabled) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
return;
}
final ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId);
if (imsMmTelManager == null) {
return;
}
try {
imsMmTelManager.setAdvancedCallingSettingEnabled(isEnabled);
} catch (IllegalArgumentException exception) {
Log.w(TAG, "Unable to change the Enhanced 4g LTE to " + isEnabled + ". subId=" + subId,
exception);
}
}
private CharSequence getEnhanced4glteModeTitle(int subId) {
CharSequence ret = mContext.getText(R.string.enhanced_4g_lte_mode_title);
try {
if (isCarrierConfigManagerKeyEnabled(
CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL,
subId,
false)) {
final PackageManager manager = mContext.getPackageManager();
final Resources resources = manager.getResourcesForApplication(
PACKAGE_PHONE);
final int resId = resources.getIdentifier(
RESOURCE_ENHANCED_4G_LTE_MODE_TITLE_VARIANT,
RESOURCE_TYPE_STRING, PACKAGE_PHONE);
ret = resources.getText(resId);
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "package name not found");
}
return ret;
}
/**
* Returns {@code true} when the key is enabled for the carrier, and {@code false} otherwise.
*/
private boolean isCarrierConfigManagerKeyEnabled(String key,
int subId, boolean defaultValue) {
final CarrierConfigManager configManager = getCarrierConfigManager();
boolean ret = defaultValue;
if (configManager != null) {
final PersistableBundle bundle = configManager.getConfigForSubId(subId);
if (bundle != null) {
ret = bundle.getBoolean(key, defaultValue);
}
}
return ret;
}
protected CarrierConfigManager getCarrierConfigManager() {
return mContext.getSystemService(CarrierConfigManager.class);
}
private PendingIntent getBroadcastIntent(String action) {
final Intent intent = new Intent(action);
intent.setClass(mContext, SliceBroadcastReceiver.class);
return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
/**
* Returns the current default voice subId obtained from SubscriptionManager
*/
protected int getDefaultVoiceSubId() {
return SubscriptionManager.getDefaultVoiceSubscriptionId();
}
/**
* Returns PendingIntent to start activity specified by action
*/
private PendingIntent getActivityIntent(String action) {
final Intent intent = new Intent(action);
intent.setPackage(SETTINGS_PACKAGE_NAME);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
}
@VisibleForTesting
VolteQueryImsState queryImsState(int subId) {
return new VolteQueryImsState(mContext, subId);
}
}