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

Commit ff0df9a6 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Fix EmergencyAffordanceService"

parents c538baa3 796cfb89
Loading
Loading
Loading
Loading
+3 −4
Original line number Original line Diff line number Diff line
@@ -3578,10 +3578,9 @@


    <!-- Do not translate. Mcc codes whose existence trigger the presence of emergency
    <!-- Do not translate. Mcc codes whose existence trigger the presence of emergency
         affordances-->
         affordances-->
    <integer-array name="config_emergency_mcc_codes" translatable="false">
    <string-array name="config_emergency_iso_country_codes" translatable="false">
        <item>404</item>
        <item>in</item>
        <item>405</item>
    </string-array>
    </integer-array>


    <!-- Package name for the device provisioning package. -->
    <!-- Package name for the device provisioning package. -->
    <string name="config_deviceProvisioningPackage"></string>
    <string name="config_deviceProvisioningPackage"></string>
+1 −1
Original line number Original line Diff line number Diff line
@@ -3168,7 +3168,7 @@
  <java-symbol type="string" name="global_action_emergency" />
  <java-symbol type="string" name="global_action_emergency" />
  <java-symbol type="string" name="config_emergency_call_number" />
  <java-symbol type="string" name="config_emergency_call_number" />
  <java-symbol type="string" name="config_emergency_dialer_package" />
  <java-symbol type="string" name="config_emergency_dialer_package" />
  <java-symbol type="array" name="config_emergency_mcc_codes" />
  <java-symbol type="array" name="config_emergency_iso_country_codes" />


  <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
  <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
  <java-symbol type="string" name="config_dozeTapSensorType" />
  <java-symbol type="string" name="config_dozeTapSensorType" />
+170 −187
Original line number Original line Diff line number Diff line
@@ -20,90 +20,80 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.provider.Settings;
import android.provider.Settings;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;


import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
import com.android.server.SystemService;


import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.List;


/**
/**
 * A service that listens to connectivity and SIM card changes and determines if the emergency mode
 * A service that listens to connectivity and SIM card changes and determines if the emergency
 * should be enabled
 * affordance should be enabled.
 */
 */
public class EmergencyAffordanceService extends SystemService {
public class EmergencyAffordanceService extends SystemService {


    private static final String TAG = "EmergencyAffordanceService";
    private static final String TAG = "EmergencyAffordanceService";
    private static final boolean DBG = false;


    private static final int NUM_SCANS_UNTIL_ABORT = 4;
    private static final String SERVICE_NAME = "emergency_affordance";


    private static final int INITIALIZE_STATE = 1;
    private static final int INITIALIZE_STATE = 1;
    private static final int CELL_INFO_STATE_CHANGED = 2;
    private static final int SUBSCRIPTION_CHANGED = 3;

    /**
    /**
     * Global setting, whether the last scan of the sim cards reveal that a sim was inserted that
     * @param arg1 slot Index
     * requires the emergency affordance. The value is a boolean (1 or 0).
     * @param arg2 0
     * @hide
     * @param obj ISO country code
     */
     */
    private static final String EMERGENCY_SIM_INSERTED_SETTING = "emergency_sim_inserted_before";
    private static final int NETWORK_COUNTRY_CHANGED = 2;

    private static final int SUBSCRIPTION_CHANGED = 3;
    private final Context mContext;
    private static final int UPDATE_AIRPLANE_MODE_STATUS = 4;
    private final ArrayList<Integer> mEmergencyCallMccNumbers;


    private final Object mLock = new Object();
    // Global Settings to override emergency affordance country ISO for debugging.
    // Available only on debug build. The value is a country ISO string in lower case (eg. "us").
    private static final String EMERGENCY_AFFORDANCE_OVERRIDE_ISO =
            "emergency_affordance_override_iso";


    private TelephonyManager mTelephonyManager;
    private final Context mContext;
    // Country ISOs that require affordance
    private final ArrayList<String> mEmergencyCallCountryIsos;
    private SubscriptionManager mSubscriptionManager;
    private SubscriptionManager mSubscriptionManager;
    private boolean mEmergencyAffordanceNeeded;
    private TelephonyManager mTelephonyManager;
    private MyHandler mHandler;
    private MyHandler mHandler;
    private int mScansCompleted;
    private boolean mAnySimNeedsEmergencyAffordance;
    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
    private boolean mAnyNetworkNeedsEmergencyAffordance;
        @Override
    private boolean mEmergencyAffordanceNeeded;
        public void onCellInfoChanged(List<CellInfo> cellInfo) {
    private boolean mAirplaneModeEnabled;
            if (!isEmergencyAffordanceNeeded()) {
    private boolean mVoiceCapable;
                requestCellScan();
            }
        }


        @Override
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        public void onCellLocationChanged(CellLocation location) {
            if (!isEmergencyAffordanceNeeded()) {
                requestCellScan();
            }
        }
    };
    private BroadcastReceiver mAirplaneModeReceiver = new BroadcastReceiver() {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            if (Settings.Global.getInt(context.getContentResolver(),
            if (TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED.equals(intent.getAction())) {
                    Settings.Global.AIRPLANE_MODE_ON, 0) == 0) {
                String countryCode = intent.getStringExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY);
                startScanning();
                int slotId = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
                requestCellScan();
                        SubscriptionManager.INVALID_SIM_SLOT_INDEX);
                mHandler.obtainMessage(
                        NETWORK_COUNTRY_CHANGED, slotId, 0, countryCode).sendToTarget();
            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
                mHandler.obtainMessage(UPDATE_AIRPLANE_MODE_STATUS).sendToTarget();
            }
            }
        }
        }
    };
    };
    private boolean mSimNeedsEmergencyAffordance;
    private boolean mNetworkNeedsEmergencyAffordance;
    private boolean mVoiceCapable;

    private void requestCellScan() {
        mHandler.obtainMessage(CELL_INFO_STATE_CHANGED).sendToTarget();
    }


    private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener
    private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener
            = new SubscriptionManager.OnSubscriptionsChangedListener() {
            = new SubscriptionManager.OnSubscriptionsChangedListener() {
@@ -116,207 +106,200 @@ public class EmergencyAffordanceService extends SystemService {
    public EmergencyAffordanceService(Context context) {
    public EmergencyAffordanceService(Context context) {
        super(context);
        super(context);
        mContext = context;
        mContext = context;
        int[] numbers = context.getResources().getIntArray(
        String[] isos = context.getResources().getStringArray(
                com.android.internal.R.array.config_emergency_mcc_codes);
                com.android.internal.R.array.config_emergency_iso_country_codes);
        mEmergencyCallMccNumbers = new ArrayList<>(numbers.length);
        mEmergencyCallCountryIsos = new ArrayList<>(isos.length);
        for (int i = 0; i < numbers.length; i++) {
        for (String iso : isos) {
            mEmergencyCallMccNumbers.add(numbers[i]);
            mEmergencyCallCountryIsos.add(iso);
        }
        }
        }


    private void updateEmergencyAffordanceNeeded() {
        if (Build.IS_DEBUGGABLE) {
        synchronized (mLock) {
            String overrideIso = Settings.Global.getString(
            mEmergencyAffordanceNeeded = mVoiceCapable && (mSimNeedsEmergencyAffordance ||
                    mContext.getContentResolver(), EMERGENCY_AFFORDANCE_OVERRIDE_ISO);
                    mNetworkNeedsEmergencyAffordance);
            if (!TextUtils.isEmpty(overrideIso)) {
            Settings.Global.putInt(mContext.getContentResolver(),
                if (DBG) Slog.d(TAG, "Override ISO to " + overrideIso);
                    Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
                mEmergencyCallCountryIsos.clear();
                    mEmergencyAffordanceNeeded ? 1 : 0);
                mEmergencyCallCountryIsos.add(overrideIso);
            if (mEmergencyAffordanceNeeded) {
                stopScanning();
            }
            }
        }
        }
    }
    }


    private void stopScanning() {
        synchronized (mLock) {
            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
            mScansCompleted = 0;
        }
    }

    private boolean isEmergencyAffordanceNeeded() {
        synchronized (mLock) {
            return mEmergencyAffordanceNeeded;
        }
    }

    @Override
    @Override
    public void onStart() {
    public void onStart() {
        if (DBG) Slog.i(TAG, "onStart");
        publishBinderService(SERVICE_NAME, new BinderService());
    }
    }


    @Override
    @Override
    public void onBootPhase(int phase) {
    public void onBootPhase(int phase) {
        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
            mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
            if (DBG) Slog.i(TAG, "onBootPhase");
            mVoiceCapable = mTelephonyManager.isVoiceCapable();
            handleThirdPartyBootPhase();
            if (!mVoiceCapable) {
                updateEmergencyAffordanceNeeded();
                return;
            }
            mSubscriptionManager = SubscriptionManager.from(mContext);
            HandlerThread thread = new HandlerThread(TAG);
            thread.start();
            mHandler = new MyHandler(thread.getLooper());
            mHandler.obtainMessage(INITIALIZE_STATE).sendToTarget();
            startScanning();
            IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
            mContext.registerReceiver(mAirplaneModeReceiver, filter);
            mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionChangedListener);
        }
        }
    }
    }


    private void startScanning() {
        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_INFO
                | PhoneStateListener.LISTEN_CELL_LOCATION);
    }

    /** Handler to do the heavier work on */
    /** Handler to do the heavier work on */
    private class MyHandler extends Handler {
    private class MyHandler extends Handler {

        public MyHandler(Looper l) {
        public MyHandler(Looper l) {
            super(l);
            super(l);
        }
        }


        @Override
        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            if (DBG) Slog.d(TAG, "handleMessage: " + msg.what);
            switch (msg.what) {
            switch (msg.what) {
                case INITIALIZE_STATE:
                case INITIALIZE_STATE:
                    handleInitializeState();
                    handleInitializeState();
                    break;
                    break;
                case CELL_INFO_STATE_CHANGED:
                case NETWORK_COUNTRY_CHANGED:
                    handleUpdateCellInfo();
                    final String countryIso = (String) msg.obj;
                    final int slotId = msg.arg1;
                    handleNetworkCountryChanged(countryIso, slotId);
                    break;
                    break;
                case SUBSCRIPTION_CHANGED:
                case SUBSCRIPTION_CHANGED:
                    handleUpdateSimSubscriptionInfo();
                    handleUpdateSimSubscriptionInfo();
                    break;
                    break;
                case UPDATE_AIRPLANE_MODE_STATUS:
                    handleUpdateAirplaneModeStatus();
                    break;
                default:
                    Slog.e(TAG, "Unexpected message received: " + msg.what);
            }
            }
        }
        }
    }
    }


    private void handleInitializeState() {
    private void handleInitializeState() {
        if (handleUpdateSimSubscriptionInfo()) {
        if (DBG) Slog.d(TAG, "handleInitializeState");
            return;
        handleUpdateAirplaneModeStatus();
        handleUpdateSimSubscriptionInfo();
        updateNetworkCountry();
        updateEmergencyAffordanceNeeded();
    }
    }
        if (handleUpdateCellInfo()) {

    private void handleThirdPartyBootPhase() {
        if (DBG) Slog.d(TAG, "handleThirdPartyBootPhase");
        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
        mVoiceCapable = mTelephonyManager.isVoiceCapable();
        if (!mVoiceCapable) {
            updateEmergencyAffordanceNeeded();
            return;
            return;
        }
        }
        updateEmergencyAffordanceNeeded();

        HandlerThread thread = new HandlerThread(TAG);
        thread.start();
        mHandler = new MyHandler(thread.getLooper());

        mSubscriptionManager = SubscriptionManager.from(mContext);
        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionChangedListener);

        IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        filter.addAction(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED);
        mContext.registerReceiver(mBroadcastReceiver, filter);

        mHandler.obtainMessage(INITIALIZE_STATE).sendToTarget();
    }

    private void handleUpdateAirplaneModeStatus() {
        mAirplaneModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
        if (DBG) Slog.d(TAG, "APM status updated to " + mAirplaneModeEnabled);
    }
    }


    private boolean handleUpdateSimSubscriptionInfo() {
    private void handleUpdateSimSubscriptionInfo() {
        boolean neededBefore = simNeededAffordanceBefore();
        boolean neededNow = neededBefore;
        List<SubscriptionInfo> activeSubscriptionInfoList =
        List<SubscriptionInfo> activeSubscriptionInfoList =
                mSubscriptionManager.getActiveSubscriptionInfoList();
                mSubscriptionManager.getActiveSubscriptionInfoList();
        if (DBG) Slog.d(TAG, "handleUpdateSimSubscriptionInfo: " + activeSubscriptionInfoList);
        if (activeSubscriptionInfoList == null) {
        if (activeSubscriptionInfoList == null) {
            setSimNeedsEmergencyAffordance(neededNow);
            return;
            return neededNow;
        }
        }

        boolean needsAffordance = false;
        for (SubscriptionInfo info : activeSubscriptionInfoList) {
        for (SubscriptionInfo info : activeSubscriptionInfoList) {
            int mcc = info.getMcc();
            if (isoRequiresEmergencyAffordance(info.getCountryIso())) {
            if (mccRequiresEmergencyAffordance(mcc)) {
                needsAffordance = true;
                neededNow = true;
                break;
                break;
            } else if (mcc != 0 && mcc != Integer.MAX_VALUE){
                // a Sim with a different mcc code was found
                neededNow = false;
            }
            String simOperator = mTelephonyManager
                    .createForSubscriptionId(info.getSubscriptionId()).getSimOperator();
            mcc = 0;
            if (simOperator != null && simOperator.length() >= 3) {
                mcc = Integer.parseInt(simOperator.substring(0, 3));
            }
            if (mcc != 0) {
                if (mccRequiresEmergencyAffordance(mcc)) {
                    neededNow = true;
                    break;
                } else {
                    // a Sim with a different mcc code was found
                    neededNow = false;
                }
            }
            }
            }
        setSimNeedsEmergencyAffordance(neededNow);
        return neededNow;
        }
        }


    private void setSimNeedsEmergencyAffordance(boolean simNeedsEmergencyAffordance) {
        mAnySimNeedsEmergencyAffordance = needsAffordance;
        if (simNeededAffordanceBefore() != simNeedsEmergencyAffordance) {
            Settings.Global.putInt(mContext.getContentResolver(),
                    EMERGENCY_SIM_INSERTED_SETTING,
                    simNeedsEmergencyAffordance ? 1 : 0);
        }
        if (simNeedsEmergencyAffordance != mSimNeedsEmergencyAffordance) {
            mSimNeedsEmergencyAffordance = simNeedsEmergencyAffordance;
        updateEmergencyAffordanceNeeded();
        updateEmergencyAffordanceNeeded();
    }
    }

    private void handleNetworkCountryChanged(String countryIso, int slotId) {
        if (DBG) {
            Slog.d(TAG, "handleNetworkCountryChanged: countryIso=" + countryIso
                    + ", slotId=" + slotId);
        }
        }


    private boolean simNeededAffordanceBefore() {
        if (TextUtils.isEmpty(countryIso) && mAirplaneModeEnabled) {
        return Settings.Global.getInt(mContext.getContentResolver(),
            Slog.w(TAG, "Ignore empty countryIso report when APM is on.");
                EMERGENCY_SIM_INSERTED_SETTING, 0) != 0;
            return;
        }
        }


    private boolean handleUpdateCellInfo() {
        updateNetworkCountry();
        List<CellInfo> cellInfos = mTelephonyManager.getAllCellInfo();

        if (cellInfos == null) {
        updateEmergencyAffordanceNeeded();
            return false;
    }
    }
        boolean stopScanningAfterScan = false;

        for (CellInfo cellInfo : cellInfos) {
    private void updateNetworkCountry() {
            int mcc = 0;
        boolean needsAffordance = false;
            if (cellInfo instanceof CellInfoGsm) {

                mcc = ((CellInfoGsm) cellInfo).getCellIdentity().getMcc();
        final int activeModems = mTelephonyManager.getActiveModemCount();
            } else if (cellInfo instanceof CellInfoLte) {
        for (int i = 0; i < activeModems; i++) {
                mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMcc();
            String countryIso = mTelephonyManager.getNetworkCountryIso(i);
            } else if (cellInfo instanceof CellInfoWcdma) {
            if (DBG) Slog.d(TAG, "UpdateNetworkCountry: slotId=" + i + " countryIso=" + countryIso);
                mcc = ((CellInfoWcdma) cellInfo).getCellIdentity().getMcc();
            if (isoRequiresEmergencyAffordance(countryIso)) {
                needsAffordance = true;
                break;
            }
            }
            if (mccRequiresEmergencyAffordance(mcc)) {
                setNetworkNeedsEmergencyAffordance(true);
                return true;
            } else if (mcc != 0 && mcc != Integer.MAX_VALUE) {
                // we found an mcc that isn't in the list, abort
                stopScanningAfterScan = true;
        }
        }

        mAnyNetworkNeedsEmergencyAffordance = needsAffordance;

        updateEmergencyAffordanceNeeded();
    }
    }
        if (stopScanningAfterScan) {

            stopScanning();
    private boolean isoRequiresEmergencyAffordance(String iso) {
        } else {
        return mEmergencyCallCountryIsos.contains(iso);
            onCellScanFinishedUnsuccessful();
    }
    }
        setNetworkNeedsEmergencyAffordance(false);

        return false;
    private void updateEmergencyAffordanceNeeded() {
        if (DBG) {
            Slog.d(TAG, "updateEmergencyAffordanceNeeded: mEmergencyAffordanceNeeded="
                    + mEmergencyAffordanceNeeded + ", mVoiceCapable=" + mVoiceCapable
                    + ", mAnySimNeedsEmergencyAffordance=" + mAnySimNeedsEmergencyAffordance
                    + ", mAnyNetworkNeedsEmergencyAffordance="
                    + mAnyNetworkNeedsEmergencyAffordance);
        }
        }
        boolean lastAffordanceNeeded = mEmergencyAffordanceNeeded;


    private void setNetworkNeedsEmergencyAffordance(boolean needsAffordance) {
        mEmergencyAffordanceNeeded = mVoiceCapable
        synchronized (mLock) {
                && (mAnySimNeedsEmergencyAffordance || mAnyNetworkNeedsEmergencyAffordance);
            mNetworkNeedsEmergencyAffordance = needsAffordance;

            updateEmergencyAffordanceNeeded();
        if (lastAffordanceNeeded != mEmergencyAffordanceNeeded) {
            Settings.Global.putInt(mContext.getContentResolver(),
                    Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
                    mEmergencyAffordanceNeeded ? 1 : 0);
        }
        }
    }
    }


    private void onCellScanFinishedUnsuccessful() {
    private void dumpInternal(IndentingPrintWriter ipw) {
        synchronized (mLock) {
        ipw.println("EmergencyAffordanceService (dumpsys emergency_affordance) state:\n");
            mScansCompleted++;
        ipw.println("mEmergencyAffordanceNeeded=" + mEmergencyAffordanceNeeded);
            if (mScansCompleted >= NUM_SCANS_UNTIL_ABORT) {
        ipw.println("mVoiceCapable=" + mVoiceCapable);
                stopScanning();
        ipw.println("mAnySimNeedsEmergencyAffordance=" + mAnySimNeedsEmergencyAffordance);
            }
        ipw.println("mAnyNetworkNeedsEmergencyAffordance=" + mAnyNetworkNeedsEmergencyAffordance);
        ipw.println("mEmergencyCallCountryIsos=" + String.join(",", mEmergencyCallCountryIsos));
    }
    }

    private final class BinderService extends Binder {
        @Override
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
                return;
            }
            }


    private boolean mccRequiresEmergencyAffordance(int mcc) {
            dumpInternal(new IndentingPrintWriter(pw, "  "));
        return mEmergencyCallMccNumbers.contains(mcc);
        }
    }
    }
}
}
+486 −0

File added.

Preview size limit exceeded, changes collapsed.