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

Commit fbe1293a authored by Bonian Chen's avatar Bonian Chen
Browse files

[Settings] fix for Wifi calling settings page crash

UI crash reported due to accessing telephony framework API with invalid
subscription ID from SIM. Which comes with multiple reason.

Besides of avoidance of crash, following updates are also required:
1. Close wifi calling settings UI when pSIM or eSIM not available or
inserted.
2. Keep the selection of tab (under multi-SIM) when screen rotate
3. Only show 1 SIM when multi-SIM are grouped together

Bug: 149190278
Test: local
Change-Id: Ied9a088b6ee5da66972f27649cc07f4a31304f17
parent d20c257a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Lifecycle;

import com.android.internal.util.CollectionUtils;
import com.android.settings.R;
@@ -68,6 +69,7 @@ public class MobileNetworkActivity extends SettingsBaseActivity
    // Set initial value to true allows subscription information fragment to be re-created when
    // Activity re-create occur.
    private boolean mFragmentForceReload = true;
    private boolean mPendingSubscriptionChange = false;

    @Override
    protected void onNewIntent(Intent intent) {
@@ -155,6 +157,10 @@ public class MobileNetworkActivity extends SettingsBaseActivity
     * Implementation of ProxySubscriptionManager.OnActiveSubscriptionChangedListener
     */
    public void onChanged() {
        if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
            mPendingSubscriptionChange = true;
            return;
        }
        SubscriptionInfo info = getSubscription();
        int oldSubIndex = mCurSubscriptionId;
        updateSubscriptions(info, null);
@@ -180,6 +186,10 @@ public class MobileNetworkActivity extends SettingsBaseActivity
        super.onStart();
        // updateSubscriptions doesn't need to be called, onChanged will always be called after we
        // register a listener.
        if (mPendingSubscriptionChange) {
            mPendingSubscriptionChange = false;
            onChanged();
        }
    }

    @Override
+145 −26
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.settings.wifi.calling;

import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
@@ -29,12 +30,14 @@ import android.view.ViewGroup;

import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;

import com.android.internal.util.CollectionUtils;
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.network.ActiveSubscriptionsListener;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.ims.WifiCallingQueryImsState;
import com.android.settings.search.actionbar.SearchMenuController;
@@ -42,6 +45,9 @@ import com.android.settings.support.actionbar.HelpResourceProvider;
import com.android.settings.widget.RtlCompatibleViewPager;
import com.android.settings.widget.SlidingTabLayout;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
@@ -50,7 +56,10 @@ import java.util.List;
 */
public class WifiCallingSettings extends InstrumentedFragment implements HelpResourceProvider {
    private static final String TAG = "WifiCallingSettings";
    private int mConstructionSubId;
    private List<SubscriptionInfo> mSil;
    private ActiveSubscriptionsListener mSubscriptionChangeListener;
    private static final int [] EMPTY_SUB_ID_LIST = new int[0];

    //UI objects
    private RtlCompatibleViewPager mViewPager;
@@ -95,16 +104,26 @@ public class WifiCallingSettings extends InstrumentedFragment implements HelpRes
        return view;
    }

    private int getConstructionSubId(Bundle bundle) {
        int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;

        Intent intent = getActivity().getIntent();
        if (intent != null) {
            subId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        }
        if ((subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) && (bundle != null)) {
            subId = bundle.getInt(Settings.EXTRA_SUB_ID,
                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        }
        return subId;
    }

    private void maybeSetViewForSubId() {
        if (mSil == null) {
            return;
        }
        final Intent intent = getActivity().getIntent();
        if (intent == null) {
            return;
        }
        final int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        int subId = mConstructionSubId;
        if (SubscriptionManager.isValidSubscriptionId(subId)) {
            for (SubscriptionInfo subInfo : mSil) {
                if (subId == subInfo.getSubscriptionId()) {
@@ -117,11 +136,15 @@ public class WifiCallingSettings extends InstrumentedFragment implements HelpRes

    @Override
    public void onCreate(Bundle icicle) {
        mConstructionSubId = getConstructionSubId(icicle);
        super.onCreate(icicle);
        Log.d(TAG, "SubId=" + mConstructionSubId);

        // TODO: besides in onCreate, we should also update subList when SIM / Sub status
        // changes.
        updateSubList();
        if (mConstructionSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            // Only config Wfc if it's enabled by platform.
            mSubscriptionChangeListener = getSubscriptionChangeListener(getContext());
        }
        mSil = updateSubList();
    }

    @Override
@@ -135,6 +158,26 @@ public class WifiCallingSettings extends InstrumentedFragment implements HelpRes
        }

        updateTitleForCurrentSub();

        if (mSubscriptionChangeListener != null) {
            mSubscriptionChangeListener.start();
        }
    }

    @Override
    public void onStop() {
        if (mSubscriptionChangeListener != null) {
            mSubscriptionChangeListener.stop();
        }

        super.onStop();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // keep subscription ID for recreation
        outState.putInt(Settings.EXTRA_SUB_ID, mConstructionSubId);
    }

    @Override
@@ -160,11 +203,11 @@ public class WifiCallingSettings extends InstrumentedFragment implements HelpRes

        @Override
        public Fragment getItem(int position) {
            Log.d(TAG, "Adapter getItem " + position);
            int subId = mSil.get(position).getSubscriptionId();
            Log.d(TAG, "Adapter getItem " + position + " for subId=" + subId);
            final Bundle args = new Bundle();
            args.putBoolean(SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR, false);
            args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID,
                    mSil.get(position).getSubscriptionId());
            args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID, subId);
            final WifiCallingSettingsForSub fragment = new WifiCallingSettingsForSub();
            fragment.setArguments(args);

@@ -190,22 +233,27 @@ public class WifiCallingSettings extends InstrumentedFragment implements HelpRes
        }
    }

    private void updateSubList() {
        mSil = SubscriptionUtil.getActiveSubscriptions(
                getContext().getSystemService(SubscriptionManager.class));
    @VisibleForTesting
    protected List<SubscriptionInfo> getSelectableSubscriptions(Context context) {
        return SubscriptionUtil.getSelectableSubscriptionInfoList(context);
    }

        // Only config Wfc if it's enabled by platform.
        if (mSil == null) {
            return;
    private List<SubscriptionInfo> updateSubList() {
        List<SubscriptionInfo> subInfoList = getSelectableSubscriptions(getContext());

        if (subInfoList == null) {
            return Collections.emptyList();
        }
        for (int i = 0; i < mSil.size(); ) {
            final SubscriptionInfo info = mSil.get(i);
            if (!queryImsState(info.getSubscriptionId()).isWifiCallingProvisioned()) {
                mSil.remove(i);
            } else {
                i++;
        List<SubscriptionInfo> selectedList = new ArrayList<SubscriptionInfo>();
        for (SubscriptionInfo subInfo : subInfoList) {
            int subId = subInfo.getSubscriptionId();
            try {
                if (queryImsState(subId).isWifiCallingProvisioned()) {
                    selectedList.add(subInfo);
                }
            } finally {}
        }
        return selectedList;
    }

    private void updateTitleForCurrentSub() {
@@ -218,7 +266,78 @@ public class WifiCallingSettings extends InstrumentedFragment implements HelpRes
    }

    @VisibleForTesting
    WifiCallingQueryImsState queryImsState(int subId) {
    protected WifiCallingQueryImsState queryImsState(int subId) {
        return new WifiCallingQueryImsState(getContext(), subId);
    }

    @VisibleForTesting
    protected ActiveSubscriptionsListener getSubscriptionChangeListener(Context context) {
        return new ActiveSubscriptionsListener(context.getMainLooper(), context) {
            public void onChanged() {
                onSubscriptionChange(context);
            }
        };
    }

    protected void onSubscriptionChange(Context context) {
        if (mSubscriptionChangeListener == null) {
            return;
        }
        int [] previousSubIdList = subscriptionIdList(mSil);
        List<SubscriptionInfo> updateList = updateSubList();
        int [] currentSubIdList = subscriptionIdList(updateList);

        if (currentSubIdList.length > 0) {
            // only keep fragment when any provisioned subscription is available
            if (previousSubIdList.length == 0) {
                // initial loading of list
                mSil = updateList;
                return;
            }
            if (previousSubIdList.length == currentSubIdList.length) {
                // same number of subscriptions
                if ( (!containsSubId(previousSubIdList, mConstructionSubId))
                        // original request not yet appears in list
                        || containsSubId(currentSubIdList, mConstructionSubId) )
                        // original request appears in list
                {
                    mSil = updateList;
                    return;
                }
            }
        }
        Log.d(TAG, "Closed subId=" + mConstructionSubId
                + " due to subscription change: " + Arrays.toString(previousSubIdList)
                + " -> " + Arrays.toString(currentSubIdList));

        // close this fragment when no provisioned subscriptions available
        if (mSubscriptionChangeListener != null) {
            mSubscriptionChangeListener.stop();
            mSubscriptionChangeListener = null;
        }

        // close this fragment
        finish();
    }

    protected void finish() {
        FragmentActivity activity = getActivity();
        if (activity == null) return;
        if (getFragmentManager().getBackStackEntryCount() > 0) {
            getFragmentManager().popBackStack();
        } else {
            activity.finish();
        }
    }

    protected int [] subscriptionIdList(List<SubscriptionInfo> subInfoList) {
        return (subInfoList == null) ? EMPTY_SUB_ID_LIST :
                subInfoList.stream().mapToInt(subInfo -> (subInfo == null) ?
                SubscriptionManager.INVALID_SUBSCRIPTION_ID : subInfo.getSubscriptionId())
                .toArray();
    }

    protected boolean containsSubId(int [] subIdArray, int subIdLookUp) {
        return Arrays.stream(subIdArray).anyMatch(subId -> (subId == subIdLookUp));
    }
}