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

Commit 19e92116 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8693198 from fcd16a7e to tm-d1-release

Change-Id: Ia4e6ef82fb7e1734d7b9dae6a7697654bb4abcf5
parents f5ff8ebd fcd16a7e
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
@@ -47,6 +48,8 @@ import com.android.internal.telephony.util.TelephonyUtils;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Set;

/**
 * Manages long-lived bindings to carrier services
@@ -71,6 +74,8 @@ public class CarrierServiceBindHelper {
    public SparseArray<AppBinding> mBindings = new SparseArray();
    @VisibleForTesting
    public SparseArray<String> mLastSimState = new SparseArray<>();
    // TODO(b/201423849): Clean up PackageChangeReceiver/UserUnlockedReceiver/SIM State change if
    // CarrierServiceChangeCallback can cover the cases
    private final PackageChangeReceiver mPackageMonitor = new CarrierServicePackageMonitor();
    private final LocalLog mLocalLog = new LocalLog(100);

@@ -90,6 +95,30 @@ public class CarrierServiceBindHelper {
        }
    };

    private class CarrierServiceChangeCallback implements
            TelephonyManager.CarrierPrivilegesCallback {
        final int mPhoneId;

        CarrierServiceChangeCallback(int phoneId) {
            this.mPhoneId = phoneId;
        }

        @Override
        public void onCarrierPrivilegesChanged(Set<String> privilegedPackageNames,
                Set<Integer> privilegedUids) {
            // Ignored, not interested here
        }

        @Override
        public void onCarrierServiceChanged(String carrierServicePackageName,
                int carrierServiceUid) {
            logdWithLocalLog("onCarrierServiceChanged, carrierServicePackageName="
                    + carrierServicePackageName + ", carrierServiceUid=" + carrierServiceUid
                    + ", mPhoneId=" + mPhoneId);
            mHandler.sendMessage(mHandler.obtainMessage(EVENT_REBIND, mPhoneId));
        }
    }

    private static final int EVENT_REBIND = 0;
    @VisibleForTesting
    public static final int EVENT_PERFORM_IMMEDIATE_UNBIND = 1;
@@ -123,6 +152,8 @@ public class CarrierServiceBindHelper {
                case EVENT_MULTI_SIM_CONFIG_CHANGED:
                    updateBindingsAndSimStates();
                    break;
                default:
                    Log.e(LOG_TAG, "Unsupported event received: " + msg.what);
            }
        }
    };
@@ -162,6 +193,7 @@ public class CarrierServiceBindHelper {

        // If prevLen > newLen, dispose AppBinding and simState objects.
        for (int phoneId = newLen; phoneId < prevLen; phoneId++) {
            mBindings.get(phoneId).tearDown();
            mBindings.get(phoneId).unbind(true);
            mBindings.delete(phoneId);
            mLastSimState.delete(phoneId);
@@ -193,9 +225,23 @@ public class CarrierServiceBindHelper {
        private String carrierPackage;
        private String carrierServiceClass;
        private long mUnbindScheduledUptimeMillis = -1;
        private final CarrierServiceChangeCallback mCarrierServiceChangeCallback;

        public AppBinding(int phoneId) {
            this.phoneId = phoneId;
            this.mCarrierServiceChangeCallback = new CarrierServiceChangeCallback(phoneId);
            TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
            if (tm != null) {
                tm.registerCarrierPrivilegesCallback(phoneId, new HandlerExecutor(mHandler),
                        mCarrierServiceChangeCallback);
            }
        }

        public void tearDown() {
            TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
            if (tm != null && mCarrierServiceChangeCallback != null) {
                tm.unregisterCarrierPrivilegesCallback(mCarrierServiceChangeCallback);
            }
        }

        public int getPhoneId() {
@@ -365,6 +411,7 @@ public class CarrierServiceBindHelper {
            pw.println("  unbindCount: " + unbindCount);
            pw.println("  lastUnbindMillis: " + lastUnbindMillis);
            pw.println("  mUnbindScheduledUptimeMillis: " + mUnbindScheduledUptimeMillis);
            pw.println("  mCarrierServiceChangeCallback: " + mCarrierServiceChangeCallback);
            pw.println();
        }
    }
@@ -405,27 +452,32 @@ public class CarrierServiceBindHelper {
    private class CarrierServicePackageMonitor extends PackageChangeReceiver {
        @Override
        public void onPackageAdded(String packageName) {
            logdWithLocalLog("onPackageAdded: " + packageName);
            evaluateBinding(packageName, true /* forceUnbind */);
        }

        @Override
        public void onPackageRemoved(String packageName) {
            logdWithLocalLog("onPackageRemoved: " + packageName);
            evaluateBinding(packageName, true /* forceUnbind */);
        }

        @Override
        public void onPackageUpdateFinished(String packageName) {
            logdWithLocalLog("onPackageUpdateFinished: " + packageName);
            evaluateBinding(packageName, true /* forceUnbind */);
        }

        @Override
        public void onPackageModified(String packageName) {
            logdWithLocalLog("onPackageModified: " + packageName);
            evaluateBinding(packageName, false /* forceUnbind */);
        }

        @Override
        public void onHandleForceStop(String[] packages, boolean doit) {
            if (doit) {
                logdWithLocalLog("onHandleForceStop: " + Arrays.toString(packages));
                for (String packageName : packages) {
                    evaluateBinding(packageName, true /* forceUnbind */);
                }
+48 −36
Original line number Diff line number Diff line
@@ -285,7 +285,6 @@ public class ServiceStateTracker extends Handler {
    // Timeout event used when delaying radio power off to wait for IMS deregistration to happen.
    private static final int EVENT_POWER_OFF_RADIO_IMS_DEREG_TIMEOUT   = 62;
    protected static final int EVENT_RESET_LAST_KNOWN_CELL_IDENTITY    = 63;
    private static final int EVENT_REGISTER_DATA_NETWORK_EXISTING_CHANGED = 64;
    // Telecom has un/registered a PhoneAccount that provides OTT voice calling capability, e.g.
    // wi-fi calling.
    protected static final int EVENT_TELECOM_VOICE_SERVICE_STATE_OVERRIDE_CHANGED = 65;
@@ -620,11 +619,11 @@ public class ServiceStateTracker extends Handler {
    private int mLastKnownAreaCode = CellInfo.UNAVAILABLE;

    /**
     * Indicating if there is any data network existing. This is used in airplane mode turning on
     * scenario, where service state tracker should wait all data disconnected before powering
     * down the modem.
     * Data network controller callback for all data disconnected. This is used when turning on
     * airplane mode, where service state tracker should wait for all data disconnected on all
     * subscriptions before powering down the modem.
     */
    private boolean mAnyDataExisting = false;
    private DataNetworkControllerCallback mDataDisconnectedCallback;

    public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
        mNitzState = TelephonyComponentFactory.getInstance()
@@ -722,7 +721,15 @@ public class ServiceStateTracker extends Handler {
                CarrierServiceStateTracker.CARRIER_EVENT_IMS_CAPABILITIES_CHANGED, null);

        if (mPhone.isUsingNewDataStack()) {
            sendEmptyMessage(EVENT_REGISTER_DATA_NETWORK_EXISTING_CHANGED);
            mDataDisconnectedCallback = new DataNetworkControllerCallback(this::post) {
                @Override
                public void onAnyDataNetworkExistingChanged(boolean anyDataExisting) {
                    log("onAnyDataNetworkExistingChanged: anyDataExisting=" + anyDataExisting);
                    if (!anyDataExisting) {
                        sendEmptyMessage(EVENT_ALL_DATA_DISCONNECTED);
                    }
                }
            };
        }
    }

@@ -1471,30 +1478,26 @@ public class ServiceStateTracker extends Handler {
                }
                break;

            case EVENT_REGISTER_DATA_NETWORK_EXISTING_CHANGED: {
                mPhone.getDataNetworkController().registerDataNetworkControllerCallback(
                        new DataNetworkControllerCallback(this::post) {
                        @Override
                        public void onAnyDataNetworkExistingChanged(boolean anyDataExisting) {
                            if (mAnyDataExisting != anyDataExisting) {
                                mAnyDataExisting = anyDataExisting;
                                log("onAnyDataNetworkExistingChanged: anyDataExisting="
                                        + anyDataExisting);
                                if (!mAnyDataExisting) {
                                    sendEmptyMessage(EVENT_ALL_DATA_DISCONNECTED);
                                }
                            }
                        }
                        });
                break;
            }
            case EVENT_ALL_DATA_DISCONNECTED:
                if (mPhone.isUsingNewDataStack()) {
                    log("EVENT_ALL_DATA_DISCONNECTED");
                    if (mPendingRadioPowerOffAfterDataOff) {
                    if (!mPendingRadioPowerOffAfterDataOff) return;
                    boolean areAllDataDisconnectedOnAllPhones = true;
                    for (Phone phone : PhoneFactory.getPhones()) {
                        if (phone.getDataNetworkController().areAllDataDisconnected()) {
                            phone.getDataNetworkController()
                                    .unregisterDataNetworkControllerCallback(
                                            mDataDisconnectedCallback);
                        } else {
                            log("Still waiting for all data disconnected on phone: "
                                    + phone.getSubId());
                            areAllDataDisconnectedOnAllPhones = false;
                        }
                    }
                    if (areAllDataDisconnectedOnAllPhones) {
                        mPendingRadioPowerOffAfterDataOff = false;
                        removeMessages(EVENT_SET_RADIO_POWER_OFF);
                        if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now.");
                        if (DBG) log("Data disconnected for all phones, turn radio off now.");
                        hangupAndPowerOff();
                    }
                    return;
@@ -5010,17 +5013,27 @@ public class ServiceStateTracker extends Handler {
        synchronized (this) {
            if (!mPendingRadioPowerOffAfterDataOff) {
                if (mPhone.isUsingNewDataStack()) {
                    if (mAnyDataExisting) {
                        log("powerOffRadioSafely: Tear down all data networks.");
                    for (Phone phone : PhoneFactory.getPhones()) {
                        if (!phone.getDataNetworkController().areAllDataDisconnected()) {
                            log("powerOffRadioSafely: Data is active on phone " + phone.getSubId()
                                    + ". Wait for all data disconnect.");
                            mPendingRadioPowerOffAfterDataOff = true;
                            phone.getDataNetworkController().registerDataNetworkControllerCallback(
                                    mDataDisconnectedCallback);
                        }
                    }

                    // Tear down outside of the disconnected check to prevent race conditions.
                    mPhone.getDataNetworkController().tearDownAllDataNetworks(
                            DataNetwork.TEAR_DOWN_REASON_AIRPLANE_MODE_ON);

                    if (mPendingRadioPowerOffAfterDataOff) {
                        sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF,
                                POWER_OFF_ALL_DATA_NETWORKS_DISCONNECTED_TIMEOUT);
                    } else {
                        log("powerOffRadioSafely: No data is connected.");
                        sendEmptyMessage(EVENT_ALL_DATA_DISCONNECTED);
                        log("powerOffRadioSafely: No data is connected, turn off radio now.");
                        hangupAndPowerOff();
                    }
                    mPendingRadioPowerOffAfterDataOff = true;
                    return;
                }
                int dds = SubscriptionManager.getDefaultDataSubscriptionId();
@@ -5072,8 +5085,8 @@ public class ServiceStateTracker extends Handler {
                    msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
                    if (sendMessageDelayed(msg, 30000)) {
                        if (DBG) {
                            log("powerOffRadioSafely: Wait up to 30s for data to isconnect, then"
                                    + " turn off radio.");
                            log("powerOffRadioSafely: Wait up to 30s for data to disconnect, "
                                    + "then turn off radio.");
                        }
                        mPendingRadioPowerOffAfterDataOff = true;
                    } else {
@@ -5337,7 +5350,6 @@ public class ServiceStateTracker extends Handler {
        dumpCellInfoList(pw);
        pw.flush();
        pw.println(" mAllowedNetworkTypes=" + mAllowedNetworkTypes);
        pw.println(" mAnyDataExisting=" + mAnyDataExisting);
        pw.println(" mMaxDataCalls=" + mMaxDataCalls);
        pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls);
        pw.println(" mReasonDataDenied=" + mReasonDataDenied);
+19 −3
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.internal.telephony.data;


import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -1082,7 +1081,13 @@ public class DataNetworkController extends Handler {
                onTearDownAllDataNetworks(msg.arg1);
                break;
            case EVENT_REGISTER_DATA_NETWORK_CONTROLLER_CALLBACK:
                mDataNetworkControllerCallbacks.add((DataNetworkControllerCallback) msg.obj);
                DataNetworkControllerCallback callback = (DataNetworkControllerCallback) msg.obj;
                mDataNetworkControllerCallbacks.add(callback);
                // Notify upon registering if no data networks currently exist.
                if (mDataNetworkList.isEmpty()) {
                    callback.invokeFromExecutor(
                            () -> callback.onAnyDataNetworkExistingChanged(false));
                }
                break;
            case EVENT_UNREGISTER_DATA_NETWORK_CONTROLLER_CALLBACK:
                mDataNetworkControllerCallbacks.remove((DataNetworkControllerCallback) msg.obj);
@@ -1337,7 +1342,7 @@ public class DataNetworkController extends Handler {
    }

    /**
     * @return {@code true} internet is unmetered.
     * @return {@code true} if internet is unmetered.
     */
    public boolean isInternetUnmetered() {
        return mDataNetworkList.stream()
@@ -1349,6 +1354,17 @@ public class DataNetworkController extends Handler {
                        .hasCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
    }

    /**
     * @return {@code true} if all data networks are disconnected.
     */
    public boolean areAllDataDisconnected() {
        if (!mDataNetworkList.isEmpty()) {
            log("areAllDataDisconnected false due to: " + mDataNetworkList.stream()
                    .map(DataNetwork::name).collect(Collectors.joining(", ")));
        }
        return mDataNetworkList.isEmpty();
    }

    /**
     * @return List of the reasons why internet data is not allowed. An empty list if internet
     * is allowed.
+34 −11
Original line number Diff line number Diff line
@@ -221,14 +221,8 @@ public class DataSettingsManager extends Handler {
            }
            case EVENT_SET_DATA_ROAMING_ENABLED: {
                boolean enabled = (boolean) msg.obj;
                // Will trigger handleDataOnRoamingChange() through observer
                boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
                        Settings.Global.DATA_ROAMING, mSubId, enabled);
                if (changed) {
                    logl("DataRoamingEnabled changed to " + enabled);
                    mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
                            () -> callback.onDataRoamingEnabledChanged(enabled)));
                }
                setDataRoamingEnabledInternal(enabled);
                setDataRoamingFromUserAction();
                break;
            }
            case EVENT_SET_ALWAYS_ALLOW_MMS_DATA: {
@@ -501,13 +495,28 @@ public class DataSettingsManager extends Handler {
    }

    /**
     * Enable or disable data roaming.
     * Enable or disable data roaming from user settings.
     * @param enabled {@code true} to enable data roaming and {@code false} to disable.
     */
    public void setDataRoamingEnabled(boolean enabled) {
        obtainMessage(EVENT_SET_DATA_ROAMING_ENABLED, enabled).sendToTarget();
    }

    /**
     * Enable or disable data roaming.
     * @param enabled {@code true} to enable data roaming and {@code false} to disable.
     */
    private void setDataRoamingEnabledInternal(boolean enabled) {
        // Will trigger handleDataOnRoamingChange() through observer
        boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
                Settings.Global.DATA_ROAMING, mSubId, enabled);
        if (changed) {
            logl("DataRoamingEnabled changed to " + enabled);
            mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
                    () -> callback.onDataRoamingEnabledChanged(enabled)));
        }
    }

    /**
     * Check whether data roaming is enabled for the device based on the current
     * {@link Settings.Global#DATA_ROAMING} value.
@@ -537,7 +546,7 @@ public class DataSettingsManager extends Handler {
    public void setDefaultDataRoamingEnabled() {
        // For SSSS, this is a per-phone property from DATA_ROAMING_IS_USER_SETTING_KEY.
        // For DSDS, this is a per-sub property from Settings.Global.DATA_ROAMING + subId.
        // If the user has not manually set the value, use the default from carrier configurations.
        // If the user has not manually set the value, use the default value.
        boolean useCarrierSpecificDefault = false;
        if (mPhone.getContext().getSystemService(TelephonyManager.class).getSimCount() != 1) {
            String setting = Settings.Global.DATA_ROAMING + mPhone.getSubId();
@@ -554,7 +563,7 @@ public class DataSettingsManager extends Handler {
        log("setDefaultDataRoamingEnabled: useCarrierSpecificDefault=" + useCarrierSpecificDefault);
        if (useCarrierSpecificDefault) {
            boolean defaultVal = isDefaultDataRoamingEnabled();
            setDataRoamingEnabled(defaultVal);
            setDataRoamingEnabledInternal(defaultVal);
        }
    }

@@ -573,6 +582,17 @@ public class DataSettingsManager extends Handler {
        return sp.getBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true);
    }

    /**
     * Indicate that the user has manually enabled or disabled the data roaming value from settings.
     * If the user has not manually set the data roaming value, the default value from
     * {@link #isDefaultDataRoamingEnabled()} will continue to be used.
     */
    private void setDataRoamingFromUserAction() {
        final SharedPreferences.Editor sp = PreferenceManager
                .getDefaultSharedPreferences(mPhone.getContext()).edit();
        sp.putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true).commit();
    }

    private @NonNull DataEnabledOverride getDataEnabledOverride() {
        return new DataEnabledOverride(SubscriptionController.getInstance()
                .getDataEnabledOverrideRules(mSubId));
@@ -724,6 +744,9 @@ public class DataSettingsManager extends Handler {
        pw.println("isDataEnabled(internet)=" + isDataEnabled(ApnSetting.TYPE_DEFAULT));
        pw.println("isDataEnabled(mms)=" + isDataEnabled(ApnSetting.TYPE_MMS));
        pw.println("isUserDataEnabled=" + isUserDataEnabled());
        pw.println("isDataRoamingEnabled=" + isDataRoamingEnabled());
        pw.println("isDefaultDataRoamingEnabled=" + isDefaultDataRoamingEnabled());
        pw.println("isDataRoamingFromUserAction=" + isDataRoamingFromUserAction());
        pw.println("device_provisioned=" + Settings.Global.getInt(
                mResolver, Settings.Global.DEVICE_PROVISIONED, 0));
        pw.println("isProvisioningDataEnabled=" + isProvisioningDataEnabled());
+43 −0
Original line number Diff line number Diff line
@@ -18,10 +18,15 @@ package com.android.internal.telephony;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import android.os.Message;
import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -30,10 +35,14 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class CarrierServiceBindHelperTest extends TelephonyTest {
    private static final int PHONE_ID_0 = 0;
    private static final int PHONE_ID_1 = 1;

    CarrierServiceBindHelper mCarrierServiceBindHelper;
    @Before
    public void setUp() throws Exception {
@@ -90,4 +99,38 @@ public class CarrierServiceBindHelperTest extends TelephonyTest {
                        CarrierServiceBindHelper.EVENT_PERFORM_IMMEDIATE_UNBIND,
                        new Integer(0)));
    }

    @Test
    public void testCarrierPrivilegesCallbackRegistration() {
        // Device starts with DSDS mode
        doReturn(2).when(mTelephonyManager).getActiveModemCount();
        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
        processAllMessages();

        // Verify that CarrierPrivilegesCallbacks are registered on both phones.
        // Capture the callbacks for further verification
        ArgumentCaptor<CarrierPrivilegesCallback> phone0CallbackCaptor = ArgumentCaptor.forClass(
                CarrierPrivilegesCallback.class);
        verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_0), any(),
                phone0CallbackCaptor.capture());
        CarrierPrivilegesCallback phone0Callback = phone0CallbackCaptor.getAllValues().get(0);
        assertNotNull(phone0Callback);

        ArgumentCaptor<CarrierPrivilegesCallback> phone1CallbackCaptor = ArgumentCaptor.forClass(
                CarrierPrivilegesCallback.class);
        verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_1), any(),
                phone1CallbackCaptor.capture());
        CarrierPrivilegesCallback phone1Callback = phone1CallbackCaptor.getAllValues().get(0);
        assertNotNull(phone1Callback);

        // Switch back to single SIM.
        doReturn(1).when(mTelephonyManager).getActiveModemCount();
        PhoneConfigurationManager.notifyMultiSimConfigChange(1);
        processAllMessages();

        // Verify the callback for phone1 had been unregistered while phone0 didn't.
        verify(mTelephonyManager).unregisterCarrierPrivilegesCallback(eq(phone1Callback));
        verify(mTelephonyManager, never()).unregisterCarrierPrivilegesCallback(eq(phone0Callback));
    }
    // TODO (b/232461097): Add UT cases to cover more scenarios (user unlock, SIM state change...)
}
Loading