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

Commit e274482c authored by Chen Xu's avatar Chen Xu Committed by Android (Google) Code Review
Browse files

Merge "cold sim clean up" into nyc-mr1-dev

parents da3a5ba9 4c31e4c0
Loading
Loading
Loading
Loading
+169 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.internal.telephony;

import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;

import com.android.internal.util.ArrayUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * This class act as an CarrierSignalling Agent.
 * it load registered carrier signalling receivers from Carrier Config and cache the result to avoid
 * repeated polling and send the intent to the interested receivers.
 * each CarrierSignalAgent is associated with a phone object.
 */
public class CarrierSignalAgent {

    private static final String LOG_TAG = "CarrierSignalAgent";
    private static final boolean DBG = true;

    /** Member variables */
    private final Phone mPhone;
    /**
     * This is a map of intent action -> string array of carrier signal receiver names which are
     * interested in this intent action
     */
    private static final HashMap<String, String[]> mCachedCarrierSignalReceiverNames =
            new HashMap<>();
    /**
     * This is a map of intent action -> carrier config key of signal receiver names which are
     * interested in this intent action
     */
    private static final Map<String, String> mIntentToCarrierConfigKeyMap =
            new HashMap<String, String>() {{
                put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED,
                        CarrierConfigManager.KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY);
                put(TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE,
                        CarrierConfigManager.KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY);
                put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
                        CarrierConfigManager.KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY);
            }};

    /** Constructor */
    public CarrierSignalAgent(Phone phone) {
        mPhone = phone;
    }

    /**
     * Read carrier signalling receiver name from CarrierConfig based on the intent type
     * @return array of receiver Name: the package (a String) name / the class (a String) name
     */
    private String[] getCarrierSignalReceiverName(String intentAction) {
        String receiverType = mIntentToCarrierConfigKeyMap.get(intentAction);
        if(receiverType == null) {
            return null;
        }
        String[] receiverNames = mCachedCarrierSignalReceiverNames.get(intentAction);
        // In case of cache miss, we need to look up/load from carrier config.
        if (!mCachedCarrierSignalReceiverNames.containsKey(intentAction)) {
            CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
                    .getSystemService(Context.CARRIER_CONFIG_SERVICE);
            PersistableBundle b = null;
            if (configManager != null) {
                b = configManager.getConfig();
            }
            if (b != null) {
                receiverNames = b.getStringArray(receiverType);
                if(receiverNames!=null) {
                    for(String name: receiverNames) {
                        Rlog.d("loadCarrierSignalReceiverNames: ", name);
                    }
                }
            } else {
                // Return static default defined in CarrierConfigManager.
                receiverNames = CarrierConfigManager.getDefaultConfig().getStringArray(receiverType);
            }
            mCachedCarrierSignalReceiverNames.put(intentAction, receiverNames);
        }
        return receiverNames;
    }

    /**
     * Check if there are registered carrier broadcast receivers to handle any registered intents.
     */
    public boolean hasRegisteredCarrierSignalReceivers() {
        for(String intent : mIntentToCarrierConfigKeyMap.keySet()) {
            if(!ArrayUtils.isEmpty(getCarrierSignalReceiverName(intent))) {
                return true;
            }
        }
        return false;
    }

    public boolean notifyCarrierSignalReceivers(Intent intent) {
        // Read a list of broadcast receivers from carrier config manager
        // which are interested on certain intent type
        String[] receiverName = getCarrierSignalReceiverName(intent.getAction());
        if (receiverName == null) {
            loge("Carrier receiver name is null");
            return false;
        }
        final PackageManager packageManager = mPhone.getContext().getPackageManager();
        boolean ret = false;

        for(String name : receiverName) {
            ComponentName componentName = ComponentName.unflattenFromString(name);
            if (componentName == null) {
                loge("Carrier receiver name could not be parsed");
                return false;
            }
            intent.setComponent(componentName);
            // Check if broadcast receiver is available
            if (packageManager.queryBroadcastReceivers(intent,
                    PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
                loge("Carrier signal receiver is configured, but not available: " + name);
                break;
            }

            intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mPhone.getSubId());
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);

            try {
                mPhone.getContext().sendBroadcast(intent);
                if (DBG) log("send Intent to carrier signal receiver with action: " +
                        intent.getAction());
                ret = true;
            } catch (ActivityNotFoundException e) {
                loge("sendBroadcast failed: " + e);
            }
        }

        return ret;
    }

    /* Clear cached receiver names */
    public void reset() {
        mCachedCarrierSignalReceiverNames.clear();
    }

    private void log(String s) {
        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    }

    private void loge(String s) {
        Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    }
}
+26 −0
Original line number Diff line number Diff line
@@ -225,6 +225,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    private int mCallRingContinueToken;
    private int mCallRingDelay;
    private boolean mIsVoiceCapable = true;
    /* Used for communicate between configured CarrierSignalling receivers */
    private CarrierSignalAgent mCarrierSignalAgent;

    // Variable to cache the video capability. When RAT changes, we lose this info and are unable
    // to recover from the state. We cache it and notify listeners when they register.
@@ -424,6 +426,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        mContext = context;
        mLooper = Looper.myLooper();
        mCi = ci;
        mCarrierSignalAgent = new CarrierSignalAgent(this);
        mActionDetached = this.getClass().getPackage().getName() + ".action_detached";
        mActionAttached = this.getClass().getPackage().getName() + ".action_attached";

@@ -1718,6 +1721,10 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        return (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_ENABLED);
    }

    public CarrierSignalAgent getCarrierSignalAgent() {
        return mCarrierSignalAgent;
    }

    /**
     *  Query the CDMA roaming preference setting
     *
@@ -2616,6 +2623,25 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
                (mDcTracker.isDataPossible(apnType)));
    }


    /**
     * Action set from carrier signalling broadcast receivers to enable/disable metered apns.
     */
    public void carrierActionSetMeteredApnsEnabled(boolean enabled) {
        if(mDcTracker != null) {
            mDcTracker.carrierActionSetMeteredApnsEnabled(enabled);
        }
    }

    /**
     * Action set from carrier signalling broadcast receivers to enable/disable radio
     */
    public void carrierActionSetRadioEnabled(boolean enabled) {
        if(mDcTracker != null) {
            mDcTracker.carrierActionSetRadioEnabled(enabled);
        }
    }

    /**
     * Notify registrants of a new ringing Connection.
     * Subclasses of Phone probably want to replace this with a
+2 −0
Original line number Diff line number Diff line
@@ -114,6 +114,8 @@ public interface PhoneInternalInterface {
    static final String REASON_SIM_NOT_READY = "simNotReady";
    static final String REASON_IWLAN_AVAILABLE = "iwlanAvailable";
    static final String REASON_CARRIER_CHANGE = "carrierChange";
    static final String REASON_CARRIER_ACTION_DISABLE_METERED_APN =
            "carrierActionDisableMeteredApn";

    // Used for band mode selection methods
    static final int BM_UNSPECIFIED = RILConstants.BAND_MODE_UNSPECIFIED; // automatic
+17 −2
Original line number Diff line number Diff line
@@ -252,6 +252,8 @@ public class ServiceStateTracker extends Handler {

    private boolean mImsRegistrationOnOff = false;
    private boolean mAlarmSwitch = false;
    /** Radio is disabled by carrier. Radio power will not be override if this field is set */
    private boolean mRadioDisabledByCarrier = false;
    private PendingIntent mRadioOffIntent = null;
    private static final String ACTION_RADIO_OFF = "android.intent.action.ACTION_RADIO_OFF";
    private boolean mPowerOffDelayNeed = true;
@@ -795,6 +797,16 @@ public class ServiceStateTracker extends Handler {
        setPowerStateToDesired();
    }

    /**
     * Radio power set from carrier action. if set to false means carrier desire to turn radio off
     * and radio wont be re-enabled unless carrier explicitly turn it back on.
     * @param enable indicate if radio power is enabled or disabled from carrier action.
     */
    public void setRadioPowerFromCarrier(boolean enable) {
        mRadioDisabledByCarrier = !enable;
        setRadioPower(enable);
    }

    /**
     * These two flags manage the behavior of the cell lock -- the
     * lock should be held if either flag is true.  The intention is
@@ -2266,7 +2278,8 @@ public class ServiceStateTracker extends Handler {
                    ", mDesiredPowerState=" + mDesiredPowerState +
                    ", getRadioState=" + mCi.getRadioState() +
                    ", mPowerOffDelayNeed=" + mPowerOffDelayNeed +
                    ", mAlarmSwitch=" + mAlarmSwitch);
                    ", mAlarmSwitch=" + mAlarmSwitch +
                    ", mRadioDisabledByCarrier=" + mRadioDisabledByCarrier);
        }

        if (mPhone.isPhoneTypeGsm() && mAlarmSwitch) {
@@ -2279,7 +2292,8 @@ public class ServiceStateTracker extends Handler {

        // If we want it on and it's off, turn it on
        if (mDesiredPowerState
                && mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
                && mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF &&
                !mRadioDisabledByCarrier) {
            mCi.setRadioPower(true, null);
        } else if (!mDesiredPowerState && mCi.getRadioState().isOn()) {
            // If it's on and available and we want it off gracefully
@@ -4566,6 +4580,7 @@ public class ServiceStateTracker extends Handler {
        pw.println(" mImsRegistered=" + mImsRegistered);
        pw.println(" mImsRegistrationOnOff=" + mImsRegistrationOnOff);
        pw.println(" mAlarmSwitch=" + mAlarmSwitch);
        pw.println(" mRadioDisabledByCarrier" + mRadioDisabledByCarrier);
        pw.println(" mPowerOffDelayNeed=" + mPowerOffDelayNeed);
        pw.println(" mDeviceShuttingDown=" + mDeviceShuttingDown);
        pw.println(" mSpnUpdatePending=" + mSpnUpdatePending);
+2 −48
Original line number Diff line number Diff line
@@ -290,16 +290,12 @@ public class SubscriptionController extends ISub.Stub {
        // FIXME: consider stick this into database too
        String countryIso = getSubscriptionCountryIso(id);

        int simProvisioningStatus = cursor.getInt(cursor.getColumnIndexOrThrow(
                SubscriptionManager.SIM_PROVISIONING_STATUS));

        if (VDBG) {
            String iccIdToPrint = SubscriptionInfo.givePrintableIccid(iccId);
            logd("[getSubInfoRecord] id:" + id + " iccid:" + iccIdToPrint + " simSlotIndex:"
                    + simSlotIndex + " displayName:" + displayName + " nameSource:" + nameSource
                    + " iconTint:" + iconTint + " dataRoaming:" + dataRoaming
                    + " mcc:" + mcc + " mnc:" + mnc + " countIso:" + countryIso
                    + " simProvisioningStatus:" + simProvisioningStatus);
                    + " mcc:" + mcc + " mnc:" + mnc + " countIso:" + countryIso);
        }

        // If line1number has been set to a different number, use it instead.
@@ -308,8 +304,7 @@ public class SubscriptionController extends ISub.Stub {
            number = line1Number;
        }
        return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
                nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
                simProvisioningStatus);
                nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso);
    }

    /**
@@ -1099,47 +1094,6 @@ public class SubscriptionController extends ISub.Stub {
        return result;
    }

    /**
     * Set SimProvisioning Status by subscription ID
     * @param provisioningStatus with the subscription:
     * {@See SubscriptionManager#SIM_PROVISIONED}
     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD}
     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT}
     * @param subId the unique SubInfoRecord index in database
     * @return the number of records updated
     */
    @Override
    public int setSimProvisioningStatus(int provisioningStatus, int subId) {

        if (DBG) {
            logd("[setSimProvisioningStatus]+ provisioningStatus:" + provisioningStatus + " subId:"
                    + subId);
        }

        enforceModifyPhoneState("setSimProvisioningStatus");
        // Now that all security checks passes, perform the operation as ourselves.
        final long identity = Binder.clearCallingIdentity();
        try {
            validateSubId(subId);
            if (provisioningStatus < 0 || provisioningStatus >
                    SubscriptionManager.MAX_SIM_PROVISIONING_STATUS) {
                logd("[setSimProvisioningStatus]- fail with wrong provisioningStatus");
                return -1;
            }
            ContentValues value = new ContentValues(1);
            value.put(SubscriptionManager.SIM_PROVISIONING_STATUS, provisioningStatus);

            int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI,
                    value, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" +
                            Long.toString(subId), null);
            notifySubscriptionInfoChanged();

            return result;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public int getSlotId(int subId) {
        if (VDBG) printStackTrace("[getSlotId] subId=" + subId);
Loading