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

Commit 7e925a73 authored by Jack Yu's avatar Jack Yu Committed by android-build-merger
Browse files

Merge "Fixed data/network service binding issues"

am: 283b03b2

Change-Id: I1fa4d19b5f051b56c75993f8323846432a0bb477
parents d1df1f01 283b03b2
Loading
Loading
Loading
Loading
+93 −14
Original line number Diff line number Diff line
@@ -16,18 +16,20 @@

package com.android.internal.telephony;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.CarrierConfigManager;
import android.telephony.INetworkService;
@@ -35,6 +37,7 @@ import android.telephony.INetworkServiceCallback;
import android.telephony.NetworkRegistrationState;
import android.telephony.NetworkService;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import java.util.Hashtable;
@@ -44,8 +47,10 @@ import java.util.Map;
 * Class that serves as the layer between NetworkService and ServiceStateTracker. It helps binding,
 * sending request and registering for state change to NetworkService.
 */
public class NetworkRegistrationManager {
    private static final String TAG = NetworkRegistrationManager.class.getSimpleName();
public class NetworkRegistrationManager extends Handler {
    private final String mTag;

    private static final int EVENT_BIND_NETWORK_SERVICE = 1;

    private final int mTransportType;

@@ -60,13 +65,60 @@ public class NetworkRegistrationManager {

    private RegManagerDeathRecipient mDeathRecipient;

    private String mTargetBindingPackageName;

    private NetworkServiceConnection mServiceConnection;

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)
                    && mPhone.getPhoneId() == intent.getIntExtra(
                    CarrierConfigManager.EXTRA_SLOT_INDEX, 0)) {
                // We should wait for carrier config changed event because the target binding
                // package name can come from the carrier config. Note that we still get this event
                // even when SIM is absent.
                logd("Carrier config changed. Try to bind network service.");
                sendEmptyMessage(EVENT_BIND_NETWORK_SERVICE);
            }
        }
    };

    public NetworkRegistrationManager(int transportType, Phone phone) {
        mTransportType = transportType;
        mPhone = phone;

        String tagSuffix = "-" + ((transportType == TransportType.WWAN) ? "C" : "I");
        if (TelephonyManager.getDefault().getPhoneCount() > 1) {
            tagSuffix += "-" + mPhone.getPhoneId();
        }
        mTag = "NRM" + tagSuffix;

        mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService(
                Context.CARRIER_CONFIG_SERVICE);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        phone.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
                intentFilter, null, null);
        sendEmptyMessage(EVENT_BIND_NETWORK_SERVICE);
    }

    /**
     * Handle message events
     *
     * @param msg The message to handle
     */
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_BIND_NETWORK_SERVICE:
                bindService();
                break;
            default:
                loge("Unhandled event " + msg.what);
        }
    }

    public boolean isServiceConnected() {
@@ -79,7 +131,6 @@ public class NetworkRegistrationManager {

    public void registerForNetworkRegistrationStateChanged(Handler h, int what, Object obj) {
        logd("registerForNetworkRegistrationStateChanged");
        Registrant r = new Registrant(h, what, obj);
        mRegStateChangeRegistrants.addUnique(h, what, obj);
    }

@@ -103,7 +154,7 @@ public class NetworkRegistrationManager {
            mCallbackTable.put(callback, onCompleteMessage);
            mINetworkService.getNetworkRegistrationState(mPhone.getPhoneId(), domain, callback);
        } catch (RemoteException e) {
            Rlog.e(TAG, "getNetworkRegistrationState RemoteException " + e);
            loge("getNetworkRegistrationState RemoteException " + e);
            mCallbackTable.remove(callback);
            onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj, null, e);
            onCompleteMessage.sendToTarget();
@@ -149,6 +200,7 @@ public class NetworkRegistrationManager {
        public void onServiceDisconnected(ComponentName name) {
            logd("service " + name + " for transport "
                    + TransportType.toString(mTransportType) + " is now disconnected.");
            mTargetBindingPackageName = null;
            if (mINetworkService != null) {
                mINetworkService.asBinder().unlinkToDeath(mDeathRecipient, 0);
            }
@@ -178,19 +230,46 @@ public class NetworkRegistrationManager {
        }
    }

    private boolean bindService() {
    private void bindService() {
        String packageName = getPackageName();
        if (TextUtils.isEmpty(packageName)) {
            loge("Can't find the binding package");
            return;
        }

        if (TextUtils.equals(packageName, mTargetBindingPackageName)) {
            logd("Service " + packageName + " already bound or being bound.");
            return;
        }

        if (mINetworkService != null && mINetworkService.asBinder().isBinderAlive()) {
            // Remove the network availability updater and then unbind the service.
            try {
                mINetworkService.removeNetworkServiceProvider(mPhone.getPhoneId());
            } catch (RemoteException e) {
                loge("Cannot remove data service provider. " + e);
            }

            mPhone.getContext().unbindService(mServiceConnection);
        }

        Intent intent = new Intent(NetworkService.NETWORK_SERVICE_INTERFACE);
        intent.setPackage(getPackageName());

        try {
            // We bind this as a foreground service because it is operating directly on the SIM,
            // and we do not want it subjected to power-savings restrictions while doing so.
            logd("Trying to bind " + getPackageName() + " for transport "
                    + TransportType.toString(mTransportType));
            return mPhone.getContext().bindService(intent, new NetworkServiceConnection(),
                    Context.BIND_AUTO_CREATE);
            mServiceConnection = new NetworkServiceConnection();
            if (!mPhone.getContext().bindService(intent, mServiceConnection,
                    Context.BIND_AUTO_CREATE)) {
                loge("Cannot bind to the data service.");
                return;
            }
            mTargetBindingPackageName = packageName;
        } catch (SecurityException e) {
            loge("bindService failed " + e);
            return false;
        }
    }

@@ -228,11 +307,11 @@ public class NetworkRegistrationManager {
        return packageName;
    }

    private static int logd(String msg) {
        return Rlog.d(TAG, msg);
    private void logd(String msg) {
        Rlog.d(mTag, msg);
    }

    private static int loge(String msg) {
        return Rlog.e(TAG, msg);
    private void loge(String msg) {
        Rlog.e(mTag, msg);
    }
}
+74 −11
Original line number Diff line number Diff line
@@ -21,9 +21,11 @@ import static android.telephony.AccessNetworkConstants.TransportType.WWAN;

import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -37,6 +39,7 @@ import android.os.PersistableBundle;
import android.os.RegistrantList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import android.telephony.data.DataCallResponse;
@@ -59,11 +62,13 @@ import java.util.concurrent.ConcurrentHashMap;
 * Data service manager manages handling data requests and responses on data services (e.g.
 * Cellular data service, IWLAN data service).
 */
public class DataServiceManager {
public class DataServiceManager extends Handler {
    private static final boolean DBG = true;

    static final String DATA_CALL_RESPONSE = "data_call_response";

    private static final int EVENT_BIND_DATA_SERVICE = 1;

    private final Phone mPhone;

    private final String mTag;
@@ -86,15 +91,32 @@ public class DataServiceManager {

    private final RegistrantList mDataCallListChangedRegistrants = new RegistrantList();

    // not final because it is set by the onServiceConnected method
    private ComponentName mComponentName;
    private String mTargetBindingPackageName;

    private CellularDataServiceConnection mServiceConnection;

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)
                    && mPhone.getPhoneId() == intent.getIntExtra(
                    CarrierConfigManager.EXTRA_SLOT_INDEX, 0)) {
                // We should wait for carrier config changed event because the target binding
                // package name can come from the carrier config. Note that we still get this event
                // even when SIM is absent.
                if (DBG) log("Carrier config changed. Try to bind data service.");
                sendEmptyMessage(EVENT_BIND_DATA_SERVICE);
            }
        }
    };

    private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient {
        @Override
        public void binderDied() {
            // TODO: try to rebind the service.
            loge("DataService(" + mComponentName +  " transport type " + mTransportType
                    + ") died.");
            loge("DataService " + mTargetBindingPackageName +  ", transport type " + mTransportType
                    + " died.");
        }
    }

@@ -142,7 +164,6 @@ public class DataServiceManager {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DBG) log("onServiceConnected");
            mComponentName = name;
            mIDataService = IDataService.Stub.asInterface(service);
            mDeathRecipient = new DataServiceManagerDeathRecipient();
            mBound = true;
@@ -167,6 +188,7 @@ public class DataServiceManager {
            mIDataService = null;
            mBound = false;
            mServiceBindingChangedRegistrants.notifyResult(false);
            mTargetBindingPackageName = null;
        }
    }

@@ -240,28 +262,69 @@ public class DataServiceManager {
                Context.CARRIER_CONFIG_SERVICE);
        mPackageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
        mAppOps = (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        phone.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
                intentFilter, null, null);
        sendEmptyMessage(EVENT_BIND_DATA_SERVICE);
    }

    /**
     * Handle message events
     *
     * @param msg The message to handle
     */
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_BIND_DATA_SERVICE:
                bindDataService();
                break;
            default:
                loge("Unhandled event " + msg.what);
        }
    }

    private void bindDataService() {
        // Start by cleaning up all packages that *shouldn't* have permissions.
        revokePermissionsFromUnusedDataServices();

        String packageName = getDataServicePackageName();
        if (TextUtils.isEmpty(packageName)) {
            loge("Can't find the binding package");
            return;
        }

        if (TextUtils.equals(packageName, mTargetBindingPackageName)) {
            if (DBG) log("Service " + packageName + " already bound or being bound.");
            return;
        }

        // Start by cleaning up all packages that *shouldn't* have permissions.
        revokePermissionsFromUnusedDataServices();

        if (mIDataService != null && mIDataService.asBinder().isBinderAlive()) {
            // Remove the network availability updater and then unbind the service.
            try {
                mIDataService.removeDataServiceProvider(mPhone.getPhoneId());
            } catch (RemoteException e) {
                loge("Cannot remove data service provider. " + e);
            }

            mPhone.getContext().unbindService(mServiceConnection);
        }

        // Then pre-emptively grant the permissions to the package we will bind.
        grantPermissionsToService(packageName);

        try {
            mServiceConnection = new CellularDataServiceConnection();
            if (!mPhone.getContext().bindService(
                    new Intent(DataService.DATA_SERVICE_INTERFACE).setPackage(packageName),
                    new CellularDataServiceConnection(),
                    mServiceConnection,
                    Context.BIND_AUTO_CREATE)) {
                loge("Cannot bind to the data service.");
                return;
            }
            mTargetBindingPackageName = packageName;
        } catch (Exception e) {
            loge("Cannot bind to the data service. Exception: " + e);
        }
+13 −4
Original line number Diff line number Diff line
@@ -224,6 +224,12 @@ public class ServiceStateTrackerTest extends TelephonyTest {
        mSSTTestHandler.start();
        waitUntilReady();
        waitForMs(600);

        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 0);
        mContext.sendBroadcast(intent);
        waitForMs(100);

        logd("ServiceStateTrackerTest -Setup!");
    }

@@ -1053,10 +1059,13 @@ public class ServiceStateTrackerTest extends TelephonyTest {
    @Test
    @MediumTest
    public void testRegisterForDataRegStateOrRatChange() {
        int drs = ServiceState.STATE_IN_SERVICE;
        int rat = sst.mSS.RIL_RADIO_TECHNOLOGY_LTE;
        sst.mSS.setRilDataRadioTechnology(rat);
        sst.mSS.setDataRegState(drs);
        NetworkRegistrationState nrs = new NetworkRegistrationState.Builder()
                .setDomain(NetworkRegistrationState.DOMAIN_PS)
                .setTransportType(TransportType.WWAN)
                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
                .setRegState(NetworkRegistrationState.REG_STATE_HOME)
                .build();
        sst.mSS.addNetworkRegistrationState(nrs);
        sst.registerForDataRegStateOrRatChanged(TransportType.WWAN, mTestHandler,
                EVENT_DATA_RAT_CHANGED, null);

+5 −0
Original line number Diff line number Diff line
@@ -490,6 +490,11 @@ public class DcTrackerTest extends TelephonyTest {
        mDcTrackerTestHandler = new DcTrackerTestHandler(getClass().getSimpleName());
        mDcTrackerTestHandler.start();
        waitUntilReady();

        Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, 0);
        mContext.sendBroadcast(intent);

        waitForMs(600);
        logd("DcTrackerTest -Setup!");
    }