/*
 * Copyright 2018 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.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.PackageManager;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RegistrantList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.CarrierConfigManager;
import android.telephony.INetworkService;
import android.telephony.INetworkServiceCallback;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.NetworkService;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;

import com.android.telephony.Rlog;

import java.util.Hashtable;
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 extends Handler {
    private final String mTag;

    private static final int EVENT_BIND_NETWORK_SERVICE = 1;

    private final int mTransportType;

    private final Phone mPhone;

    private final CarrierConfigManager mCarrierConfigManager;

    // Registrants who listens registration state change callback from this class.
    private final RegistrantList mRegStateChangeRegistrants = new RegistrantList();

    private INetworkService mINetworkService;

    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(@TransportType int transportType, Phone phone) {
        mTransportType = transportType;
        mPhone = phone;

        String tagSuffix = "-" + ((transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                ? "C" : "I") + "-" + 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);
        try {
            Context contextAsUser = phone.getContext().createPackageContextAsUser(
                phone.getContext().getPackageName(), 0, UserHandle.ALL);
            contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter,
                null /* broadcastPermission */, null);
        } catch (PackageManager.NameNotFoundException e) {
            loge("Package name not found: " + e.getMessage());
        }
        PhoneConfigurationManager.registerForMultiSimConfigChange(
                this, EVENT_BIND_NETWORK_SERVICE, 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:
                rebindService();
                break;
            default:
                loge("Unhandled event " + msg.what);
        }
    }

    public boolean isServiceConnected() {
        return (mINetworkService != null) && (mINetworkService.asBinder().isBinderAlive());
    }

    public void unregisterForNetworkRegistrationInfoChanged(Handler h) {
        mRegStateChangeRegistrants.remove(h);
    }

    public void registerForNetworkRegistrationInfoChanged(Handler h, int what, Object obj) {
        logd("registerForNetworkRegistrationInfoChanged");
        mRegStateChangeRegistrants.addUnique(h, what, obj);
    }

    private final Map<NetworkRegStateCallback, Message> mCallbackTable = new Hashtable();

    public void requestNetworkRegistrationInfo(@NetworkRegistrationInfo.Domain int domain,
                                               Message onCompleteMessage) {
        if (onCompleteMessage == null) return;

        if (!isServiceConnected()) {
            loge("service not connected. Domain = "
                    + ((domain == NetworkRegistrationInfo.DOMAIN_CS) ? "CS" : "PS"));
            onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj, null,
                    new IllegalStateException("Service not connected."));
            onCompleteMessage.sendToTarget();
            return;
        }

        NetworkRegStateCallback callback = new NetworkRegStateCallback();
        try {
            mCallbackTable.put(callback, onCompleteMessage);
            mINetworkService.requestNetworkRegistrationInfo(mPhone.getPhoneId(), domain, callback);
        } catch (RemoteException e) {
            loge("requestNetworkRegistrationInfo RemoteException " + e);
            mCallbackTable.remove(callback);
            onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj, null, e);
            onCompleteMessage.sendToTarget();
        }
    }

    private class RegManagerDeathRecipient implements IBinder.DeathRecipient {

        private final ComponentName mComponentName;

        RegManagerDeathRecipient(ComponentName name) {
            mComponentName = name;
        }

        @Override
        public void binderDied() {
            // TODO: try to restart the service.
            logd("NetworkService(" + mComponentName +  " transport type "
                    + mTransportType + ") died.");
        }
    }

    private class NetworkServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            logd("service " + name + " for transport "
                    + AccessNetworkConstants.transportTypeToString(mTransportType)
                    + " is now connected.");
            mINetworkService = INetworkService.Stub.asInterface(service);
            mDeathRecipient = new RegManagerDeathRecipient(name);
            try {
                service.linkToDeath(mDeathRecipient, 0);
                mINetworkService.createNetworkServiceProvider(mPhone.getPhoneId());
                mINetworkService.registerForNetworkRegistrationInfoChanged(mPhone.getPhoneId(),
                        new NetworkRegStateCallback());
            } catch (RemoteException exception) {
                // Remote exception means that the binder already died.
                mDeathRecipient.binderDied();
                logd("RemoteException " + exception);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            logd("service " + name + " for transport "
                    + AccessNetworkConstants.transportTypeToString(mTransportType)
                    + " is now disconnected.");
            mTargetBindingPackageName = null;
        }
    }

    private class NetworkRegStateCallback extends INetworkServiceCallback.Stub {
        @Override
        public void onRequestNetworkRegistrationInfoComplete(
                int result, NetworkRegistrationInfo info) {
            logd("onRequestNetworkRegistrationInfoComplete result: "
                    + result + ", info: " + info);
            Message onCompleteMessage = mCallbackTable.remove(this);
            if (onCompleteMessage != null) {
                onCompleteMessage.arg1 = result;
                onCompleteMessage.obj = new AsyncResult(onCompleteMessage.obj,
                        new NetworkRegistrationInfo(info), null);
                onCompleteMessage.sendToTarget();
            } else {
                loge("onCompleteMessage is null");
            }
        }

        @Override
        public void onNetworkStateChanged() {
            logd("onNetworkStateChanged");
            mRegStateChangeRegistrants.notifyRegistrants();
        }
    }

    private void unbindService() {
        if (mINetworkService != null && mINetworkService.asBinder().isBinderAlive()) {
            logd("unbinding service");
            // 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);
            }
        }

        if (mServiceConnection != null) {
            mPhone.getContext().unbindService(mServiceConnection);
        }
        mINetworkService = null;
        mServiceConnection = null;
        mTargetBindingPackageName = null;
    }

    private void bindService(String packageName) {
        if (mPhone == null || !SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())) {
            loge("can't bindService with invalid phone or phoneId.");
            return;
        }

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

        Intent intent = null;
        String className = getClassName();
        if (TextUtils.isEmpty(className)) {
            intent = new Intent(NetworkService.SERVICE_INTERFACE);
            intent.setPackage(packageName);
        } else {
            ComponentName cm = new ComponentName(packageName, className);
            intent = new Intent(NetworkService.SERVICE_INTERFACE).setComponent(cm);
        }

        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 "
                    + AccessNetworkConstants.transportTypeToString(mTransportType));
            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);
        }
    }

    private void rebindService() {
        String packageName = getPackageName();
        // Do nothing if no need to rebind.
        if (SubscriptionManager.isValidPhoneId(mPhone.getPhoneId())
                && TextUtils.equals(packageName, mTargetBindingPackageName)) {
            logd("Service " + packageName + " already bound or being bound.");
            return;
        }

        unbindService();
        bindService(packageName);
    }

    private String getPackageName() {
        String packageName;
        int resourceId;
        String carrierConfig;

        switch (mTransportType) {
            case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
                resourceId = com.android.internal.R.string.config_wwan_network_service_package;
                carrierConfig = CarrierConfigManager
                        .KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING;
                break;
            case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
                resourceId = com.android.internal.R.string.config_wlan_network_service_package;
                carrierConfig = CarrierConfigManager
                        .KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING;
                break;
            default:
                throw new IllegalStateException("Transport type not WWAN or WLAN. type="
                        + mTransportType);
        }

        // Read package name from resource overlay
        packageName = mPhone.getContext().getResources().getString(resourceId);

        PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());

        if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) {
            // If carrier config overrides it, use the one from carrier config
            packageName = b.getString(carrierConfig, packageName);
        }

        return packageName;
    }

    private String getClassName() {
        String className;
        int resourceId;
        String carrierConfig;

        switch (mTransportType) {
            case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
                resourceId = com.android.internal.R.string.config_wwan_network_service_class;
                carrierConfig = CarrierConfigManager
                        .KEY_CARRIER_NETWORK_SERVICE_WWAN_CLASS_OVERRIDE_STRING;
                break;
            case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
                resourceId = com.android.internal.R.string.config_wlan_network_service_class;
                carrierConfig = CarrierConfigManager
                        .KEY_CARRIER_NETWORK_SERVICE_WLAN_CLASS_OVERRIDE_STRING;
                break;
            default:
                throw new IllegalStateException("Transport type not WWAN or WLAN. type="
                        + mTransportType);
        }

        // Read class name from resource overlay
        className = mPhone.getContext().getResources().getString(resourceId);

        PersistableBundle b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId());

        if (b != null && !TextUtils.isEmpty(b.getString(carrierConfig))) {
            // If carrier config overrides it, use the one from carrier config
            className = b.getString(carrierConfig, className);
        }

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

    private void loge(String msg) {
        Rlog.e(mTag, msg);
    }
}
