Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 606222da authored by Josh Hou's avatar Josh Hou Committed by Naina Nalluri
Browse files

Add Slices for Enhanced 4G LTE

Add Slices for Enhanced 4G LTE
Enhanced 4G LTE Slice Provider:
Create slice to display appropriate message with further instructions
Enhanced 4G LTE Slice Broadcast Reciver:
1. Change the setting via ImsManager
2. Ask to requery the slice in one second to display updated settings if 1 is valid or display appropriate message

Bug: 79270171
Test: Robotests
Test: Use support-slices-demos-debug.apk to test on device
Change-Id: I48d412de94d5d9f1ad42a299691ec5cf8001c6a1
parent 09df7d70
Loading
Loading
Loading
Loading
+295 −0
Original line number Diff line number Diff line
/*
 * 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.mobilenetwork;

import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;

import android.app.PendingIntent;
import android.content.ContentResolver;
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 androidx.core.graphics.drawable.IconCompat;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.util.Log;

import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;

import com.android.ims.ImsManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.slices.SettingsSliceProvider;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Helper class to control slices for enhanced 4g LTE settings.
 */
public class Enhanced4gLteSliceHelper {

    private static final String TAG = "Enhanced4gLteSliceHelper";

    /**
     * Settings slice path to enhanced 4g LTE setting.
     */
    public static final String PATH_ENHANCED_4G_LTE = "enhanced_4g_lte";

    /**
     * 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";

    /**
     * Slice Uri for Enhanced 4G slice
     */
    public static final Uri SLICE_URI = new Uri.Builder()
            .scheme(ContentResolver.SCHEME_CONTENT)
            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
            .appendPath(PATH_ENHANCED_4G_LTE)
            .build();
    /**
     * 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";

    /**
     * Timeout for querying enhanced 4g lte setting from ims manager.
     */
    private static final int TIMEOUT_MILLIS = 2000;

    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 (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            Log.d(TAG, "Invalid subscription Id");
            return null;
        }

        final ImsManager imsManager = getImsManager(subId);

        if (!imsManager.isVolteEnabledByPlatform()
                || !imsManager.isVolteProvisionedOnDevice()) {
            Log.d(TAG, "Setting is either not provisioned or not enabled by Platform");
            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;
        }

        try {
            return getEnhanced4gLteSlice(sliceUri,
                    isEnhanced4gLteModeEnabled(imsManager), subId);
        } catch (InterruptedException | TimeoutException | ExecutionException e) {
            Log.e(TAG, "Unable to read the current Enhanced 4g LTE status", e);
            return null;
        }
    }

    private boolean isEnhanced4gLteModeEnabled(ImsManager imsManager)
            throws InterruptedException, ExecutionException, TimeoutException {
        final FutureTask<Boolean> isEnhanced4gLteOnTask = new FutureTask<>(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return imsManager.isEnhanced4gLteModeSettingEnabledByUser();
            }
        });
        final ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(isEnhanced4gLteOnTask);

        return isEnhanced4gLteOnTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
    }

    /**
     * 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(b -> b
                        .setTitle(getEnhanced4glteModeTitle(subId))
                        .addEndItem(
                                new SliceAction(
                                        getBroadcastIntent(ACTION_ENHANCED_4G_LTE_CHANGED),
                                        null /* actionTitle */, isEnhanced4gLteEnabled))
                        .setPrimaryAction(new SliceAction(
                                getActivityIntent(ACTION_MOBILE_NETWORK_SETTINGS_ACTIVITY),
                                icon,
                                getEnhanced4glteModeTitle(subId))))
                .build();
    }

    protected ImsManager getImsManager(int subId) {
        return ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(subId));
    }

    /**
     * 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) {
        final int subId = getDefaultVoiceSubId();

        if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            final ImsManager imsManager = getImsManager(subId);
            if (imsManager.isVolteEnabledByPlatform()
                    && imsManager.isVolteProvisionedOnDevice()) {
                final boolean currentValue = imsManager.isEnhanced4gLteModeSettingEnabledByUser()
                        && imsManager.isNonTtyOrTtyOnVolteEnabled();
                final boolean newValue = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
                        currentValue);
                if (newValue != currentValue) {
                    imsManager.setEnhanced4gLteModeSetting(newValue);
                }
            }
        }
        // notify change in slice in any case to get re-queried. This would result in displaying
        // appropriate message with the updated setting.
        final Uri uri = SliceBuilderUtils.getUri(PATH_ENHANCED_4G_LTE, false /*isPlatformSlice*/);
        mContext.getContentResolver().notifyChange(uri, null);
    }

    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.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
    }
}
+22 −17
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.mobilenetwork.Enhanced4gLteSliceHelper;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
@@ -190,7 +191,6 @@ public class SettingsSliceProvider extends SliceProvider {
                Log.e(TAG, "Requested blocked slice with Uri: " + sliceUri);
                return null;
            }

        // If adding a new Slice, do not directly match Slice URIs.
        // Use {@link SlicesDatabaseAccessor}.
        if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
@@ -206,6 +206,11 @@ public class SettingsSliceProvider extends SliceProvider {
            return BluetoothSliceBuilder.getSlice(getContext());
        } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
            return LocationSliceBuilder.getSlice(getContext());
        } else if (Enhanced4gLteSliceHelper.SLICE_URI.equals(sliceUri)) {
            return FeatureFactory.getFactory(getContext())
                    .getSlicesFeatureProvider()
                    .getNewEnhanced4gLteSliceHelper(getContext())
                    .createEnhanced4gLteSlice(sliceUri);
        }

            SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED;
import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED;
import static com.android.settings.wifi.WifiSliceBuilder.ACTION_WIFI_SLICE_CHANGED;
import static com.android.settings.mobilenetwork.Enhanced4gLteSliceHelper.ACTION_ENHANCED_4G_LTE_CHANGED;

import android.app.slice.Slice;
import android.content.BroadcastReceiver;
@@ -84,6 +85,12 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
            case ACTION_ZEN_MODE_SLICE_CHANGED:
                ZenModeSliceBuilder.handleUriChange(context, intent);
                break;
            case ACTION_ENHANCED_4G_LTE_CHANGED:
                FeatureFactory.getFactory(context)
                        .getSlicesFeatureProvider()
                        .getNewEnhanced4gLteSliceHelper(context)
                        .handleEnhanced4gLteChanged(intent);
                break;
            default:
                final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI);
                if (!TextUtils.isEmpty(uriString)) {
+7 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package com.android.settings.slices;

import android.content.Context;

import com.android.settings.mobilenetwork.Enhanced4gLteSliceHelper;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;

/**
@@ -31,4 +32,10 @@ public interface SlicesFeatureProvider {
     * Gets new WifiCallingSliceHelper object
     */
    WifiCallingSliceHelper getNewWifiCallingSliceHelper(Context context);

    /**
     * Gets new Enhanced4gLteSliceHelper object
     */
    Enhanced4gLteSliceHelper getNewEnhanced4gLteSliceHelper(Context context);
}
+6 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package com.android.settings.slices;

import android.content.Context;

import com.android.settings.mobilenetwork.Enhanced4gLteSliceHelper;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
import com.android.settingslib.utils.ThreadUtils;

@@ -45,4 +46,9 @@ public class SlicesFeatureProviderImpl implements SlicesFeatureProvider {
    public WifiCallingSliceHelper getNewWifiCallingSliceHelper(Context context) {
        return new WifiCallingSliceHelper(context);
    }

    @Override
    public Enhanced4gLteSliceHelper getNewEnhanced4gLteSliceHelper(Context context) {
        return new Enhanced4gLteSliceHelper(context);
    }
}
Loading