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

Commit bb8199e8 authored by Chaohui Wang's avatar Chaohui Wang Committed by Android (Google) Code Review
Browse files

Merge "Create VideoCallingRepository" into main

parents ca8a69bd f218f762
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -221,10 +221,11 @@
                </intent>
            </Preference>

            <!-- Settings search is handled by WifiCallingSearchItem. -->
            <SwitchPreferenceCompat
                android:key="video_calling_key"
                android:title="@string/video_calling_settings_title"
                android:persistent="true"
                settings:searchable="false"
                settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController"/>

        </PreferenceCategory>
+4 −33
Original line number Diff line number Diff line
@@ -18,24 +18,17 @@ package com.android.settings.network.ims;

import android.content.Context;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsException;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

/**
 * Controller class for querying VT status
 */
public class VtQueryImsState extends ImsQueryController {
public class VtQueryImsState {

    private static final String LOG_TAG = "VtQueryImsState";

    private Context mContext;
    private int mSubId;
    private final Context mContext;
    private final int mSubId;

    /**
     * Constructor
@@ -44,9 +37,6 @@ public class VtQueryImsState extends ImsQueryController {
     * @param subId subscription's id
     */
    public VtQueryImsState(Context context, int subId) {
        super(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
                ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
                AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        mContext = context;
        mSubId = subId;
    }
@@ -62,24 +52,6 @@ public class VtQueryImsState extends ImsQueryController {
        return (new ImsQueryVtUserSetting(subId)).query();
    }

    /**
     * Check whether Video Call can be perform or not on this subscription
     *
     * @return true when Video Call can be performed, otherwise false
     */
    public boolean isReadyToVideoCall() {
        if (!isProvisionedOnDevice(mSubId)) {
            return false;
        }

        try {
            return isEnabledByPlatform(mSubId) && isServiceStateReady(mSubId);
        } catch (InterruptedException | IllegalArgumentException | ImsException exception) {
            Log.w(LOG_TAG, "fail to get Vt ready. subId=" + mSubId, exception);
        }
        return false;
    }

    /**
     * Get allowance status for user to alter configuration
     *
@@ -89,8 +61,7 @@ public class VtQueryImsState extends ImsQueryController {
        if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
            return false;
        }
        return ((!isTtyEnabled(mContext))
                || (isTtyOnVolteEnabled(mSubId)));
        return !isTtyEnabled(mContext) || new ImsQueryTtyOnVolteStat(mSubId).query();
    }

    @VisibleForTesting
+11 −2
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ class CarrierConfigRepository(private val context: Context) {
        private val keysToRetrieve = mutableMapOf<String, KeyType>()

        override fun getBoolean(key: String): Boolean {
            check(key.endsWith("_bool")) { "Boolean key should ends with _bool" }
            checkBooleanKey(key)
            val value = cache[key]
            return if (value == null) {
                keysToRetrieve += key to KeyType.BOOLEAN
@@ -186,9 +186,18 @@ class CarrierConfigRepository(private val context: Context) {
            ListenerRegistered.getAndSet(false)
        }

        private val BooleanKeysWhichNotFollowingsNamingConventions =
            listOf(CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)

        private fun checkBooleanKey(key: String) {
            check(key.endsWith("_bool") || key in BooleanKeysWhichNotFollowingsNamingConventions) {
                "Boolean key should ends with _bool"
            }
        }

        @VisibleForTesting
        fun setBooleanForTest(subId: Int, key: String, value: Boolean) {
            check(key.endsWith("_bool")) { "Boolean key should ends with _bool" }
            checkBooleanKey(key)
            getPerSubCache(subId)[key] = BooleanConfigValue(value)
        }

+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.settings.network.telephony.DataUsagePreferenceController.Comp
import com.android.settings.network.telephony.MmsMessagePreferenceController.Companion.MmsMessageSearchItem
import com.android.settings.network.telephony.NrAdvancedCallingPreferenceController.Companion.NrAdvancedCallingSearchItem
import com.android.settings.network.telephony.RoamingPreferenceController.Companion.RoamingSearchItem
import com.android.settings.network.telephony.VideoCallingPreferenceController.Companion.VideoCallingSearchItem
import com.android.settings.network.telephony.WifiCallingPreferenceController.Companion.WifiCallingSearchItem
import com.android.settings.spa.SpaSearchLanding.BundleValue
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingFragment
@@ -122,6 +123,7 @@ class MobileNetworkSettingsSearchIndex(
                NrAdvancedCallingSearchItem(context),
                PreferredNetworkModeSearchItem(context),
                RoamingSearchItem(context),
                VideoCallingSearchItem(context),
                WifiCallingSearchItem(context),
            )
    }
+0 −234
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.network.telephony;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsMmTelManager;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;

import com.android.internal.telephony.flags.Flags;
import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.MobileDataEnabledListener;
import com.android.settings.network.ims.VolteQueryImsState;
import com.android.settings.network.ims.VtQueryImsState;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;

/**
 * Preference controller for "Video Calling"
 */
public class VideoCallingPreferenceController extends TelephonyTogglePreferenceController implements
        LifecycleObserver, OnStart, OnStop,
        MobileDataEnabledListener.Client,
        Enhanced4gBasePreferenceController.On4gLteUpdateListener {

    private static final String TAG = "VideoCallingPreference";

    private Preference mPreference;
    private PhoneTelephonyCallback mTelephonyCallback;
    @VisibleForTesting
    Integer mCallState;
    private MobileDataEnabledListener mDataContentObserver;
    private CallingPreferenceCategoryController mCallingPreferenceCategoryController;

    public VideoCallingPreferenceController(Context context, String key) {
        super(context, key);
        mDataContentObserver = new MobileDataEnabledListener(context, this);
        mTelephonyCallback = new PhoneTelephonyCallback();
    }

    @Override
    public int getAvailabilityStatus(int subId) {
        return SubscriptionManager.isValidSubscriptionId(subId)
                && isVideoCallEnabled(subId)
                ? AVAILABLE
                : CONDITIONALLY_UNAVAILABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreference = screen.findPreference(getPreferenceKey());
    }

    @Override
    public void onStart() {
        mTelephonyCallback.register(mContext, mSubId);
        mDataContentObserver.start(mSubId);
    }

    @Override
    public void onStop() {
        mTelephonyCallback.unregister();
        mDataContentObserver.stop();
    }

    @Override
    public void updateState(Preference preference) {
        super.updateState(preference);
        if ((mCallState == null) || (preference == null)) {
            Log.d(TAG, "Skip update under mCallState=" + mCallState);
            return;
        }
        final TwoStatePreference switchPreference = (TwoStatePreference) preference;
        final boolean videoCallEnabled = isVideoCallEnabled(mSubId);
        switchPreference.setVisible(videoCallEnabled);
        mCallingPreferenceCategoryController
                .updateChildVisible(getPreferenceKey(), videoCallEnabled);
        if (videoCallEnabled) {
            final boolean videoCallEditable = queryVoLteState(mSubId).isEnabledByUser()
                    && queryImsState(mSubId).isAllowUserControl();
            preference.setEnabled(videoCallEditable
                    && mCallState == TelephonyManager.CALL_STATE_IDLE);
            switchPreference.setChecked(videoCallEditable && isChecked());
        }
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
            return false;
        }
        final ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(mSubId);
        if (imsMmTelManager == null) {
            return false;
        }
        try {
            imsMmTelManager.setVtSettingEnabled(isChecked);
            return true;
        } catch (IllegalArgumentException exception) {
            Log.w(TAG, "Unable to set VT status " + isChecked + ". subId=" + mSubId,
                    exception);
        }
        return false;
    }

    @Override
    public boolean isChecked() {
        return queryImsState(mSubId).isEnabledByUser();
    }

    @VisibleForTesting
    protected boolean isImsSupported() {
        return mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_TELEPHONY_IMS);
    }

    /**
     * Init instance of VideoCallingPreferenceController.
     */
    public VideoCallingPreferenceController init(
            int subId, CallingPreferenceCategoryController callingPreferenceCategoryController) {
        mSubId = subId;
        mCallingPreferenceCategoryController = callingPreferenceCategoryController;

        return this;
    }

    @VisibleForTesting
    boolean isVideoCallEnabled(int subId) {
        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
            return false;
        }

        final PersistableBundle carrierConfig =
                CarrierConfigCache.getInstance(mContext).getConfigForSubId(subId);
        if (carrierConfig == null) {
            return false;
        }

        if (!carrierConfig.getBoolean(
                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
                && (!mContext.getSystemService(TelephonyManager.class)
                    .createForSubscriptionId(subId).isDataEnabled())) {
            return false;
        }

        return isImsSupported() && queryImsState(subId).isReadyToVideoCall();
    }

    @Override
    public void on4gLteUpdated() {
        updateState(mPreference);
    }

    private class PhoneTelephonyCallback extends TelephonyCallback implements
            TelephonyCallback.CallStateListener {

        private TelephonyManager mTelephonyManager;

        @Override
        public void onCallStateChanged(int state) {
            mCallState = state;
            updateState(mPreference);
        }

        public void register(Context context, int subId) {
            mTelephonyManager = context.getSystemService(TelephonyManager.class);
            if (SubscriptionManager.isValidSubscriptionId(subId)) {
                mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
            }
            // assign current call state so that it helps to show correct preference state even
            // before first onCallStateChanged() by initial registration.
            if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
                try {
                    mCallState = mTelephonyManager.getCallState(subId);
                } catch (UnsupportedOperationException e) {
                    // Device doesn't support FEATURE_TELEPHONY_CALLING
                    mCallState = TelephonyManager.CALL_STATE_IDLE;
                }
            } else {
                mCallState = mTelephonyManager.getCallState(subId);
            }
            mTelephonyManager.registerTelephonyCallback(context.getMainExecutor(), this);
        }

        public void unregister() {
            mCallState = null;
            mTelephonyManager.unregisterTelephonyCallback(this);
        }
    }

    /**
     * Implementation of MobileDataEnabledListener.Client
     */
    public void onMobileDataEnabledChange() {
        updateState(mPreference);
    }

    @VisibleForTesting
    VtQueryImsState queryImsState(int subId) {
        return new VtQueryImsState(mContext, subId);
    }

    @VisibleForTesting
    VolteQueryImsState queryVoLteState(int subId) {
        return new VolteQueryImsState(mContext, subId);
    }
}
Loading