/*
 * Copyright (C) 2014 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.server.telecom;

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.PackageManagerInternal;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.telecom.DefaultDialerManager;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.util.IntArray;
import android.util.Slog;

import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.SmsApplication;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.UserManagerService;

/**
 * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
 * to run in the system-server process so once it is loaded into memory it will stay running.
 * @hide
 */
public class TelecomLoaderService extends SystemService {
    private static final String TAG = "TelecomLoaderService";

    private class TelecomServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // Normally, we would listen for death here, but since telecom runs in the same process
            // as this loader (process="system") thats redundant here.
            try {
                service.linkToDeath(new IBinder.DeathRecipient() {
                    @Override
                    public void binderDied() {
                        connectToTelecom();
                    }
                }, 0);
                SmsApplication.getDefaultMmsApplication(mContext, false);
                ServiceManager.addService(Context.TELECOM_SERVICE, service);

                synchronized (mLock) {
                    if (mDefaultSmsAppRequests != null || mDefaultDialerAppRequests != null
                            || mDefaultSimCallManagerRequests != null) {
                        final PackageManagerInternal packageManagerInternal = LocalServices
                                .getService(PackageManagerInternal.class);

                        if (mDefaultSmsAppRequests != null) {
                            ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
                                    mContext, true);
                            if (smsComponent != null) {
                                final int requestCount = mDefaultSmsAppRequests.size();
                                for (int i = requestCount - 1; i >= 0; i--) {
                                    final int userid = mDefaultSmsAppRequests.get(i);
                                    mDefaultSmsAppRequests.remove(i);
                                    packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
                                            smsComponent.getPackageName(), userid);
                                }
                            }
                        }

                        if (mDefaultDialerAppRequests != null) {
                            String packageName = DefaultDialerManager.getDefaultDialerApplication(
                                    mContext);
                            if (packageName != null) {
                                final int requestCount = mDefaultDialerAppRequests.size();
                                for (int i = requestCount - 1; i >= 0; i--) {
                                    final int userId = mDefaultDialerAppRequests.get(i);
                                    mDefaultDialerAppRequests.remove(i);
                                    packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
                                            packageName, userId);
                                }
                            }
                        }
                        if (mDefaultSimCallManagerRequests != null) {
                            TelecomManager telecomManager =
                                (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
                            PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager();
                            if (phoneAccount != null) {
                                final int requestCount = mDefaultSimCallManagerRequests.size();
                                final String packageName =
                                    phoneAccount.getComponentName().getPackageName();
                                for (int i = requestCount - 1; i >= 0; i--) {
                                    final int userId = mDefaultSimCallManagerRequests.get(i);
                                    mDefaultSimCallManagerRequests.remove(i);
                                    packageManagerInternal
                                            .grantDefaultPermissionsToDefaultSimCallManager(
                                                    packageName, userId);
                                }
                            }
                        }
                    }
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed linking to death.");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            connectToTelecom();
        }
    }

    private static final ComponentName SERVICE_COMPONENT = new ComponentName(
            "com.android.server.telecom",
            "com.android.server.telecom.components.TelecomService");

    private static final String SERVICE_ACTION = "com.android.ITelecomService";

    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private IntArray mDefaultSmsAppRequests;

    @GuardedBy("mLock")
    private IntArray mDefaultDialerAppRequests;

    @GuardedBy("mLock")
    private IntArray mDefaultSimCallManagerRequests;

    private final Context mContext;

    @GuardedBy("mLock")
    private TelecomServiceConnection mServiceConnection;

    public TelecomLoaderService(Context context) {
        super(context);
        mContext = context;
        registerDefaultAppProviders();
    }

    @Override
    public void onStart() {
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == PHASE_ACTIVITY_MANAGER_READY) {
            registerDefaultAppNotifier();
            registerCarrierConfigChangedReceiver();
            connectToTelecom();
        }
    }

    private void connectToTelecom() {
        synchronized (mLock) {
            if (mServiceConnection != null) {
                // TODO: Is unbinding worth doing or wait for system to rebind?
                mContext.unbindService(mServiceConnection);
                mServiceConnection = null;
            }

            TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
            Intent intent = new Intent(SERVICE_ACTION);
            intent.setComponent(SERVICE_COMPONENT);
            int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
                    | Context.BIND_AUTO_CREATE;

            // Bind to Telecom and register the service
            if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
                mServiceConnection = serviceConnection;
            }
        }
    }


    private void registerDefaultAppProviders() {
        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);

        // Set a callback for the package manager to query the default sms app.
        packageManagerInternal.setSmsAppPackagesProvider(
                new PackageManagerInternal.PackagesProvider() {
            @Override
            public String[] getPackages(int userId) {
                synchronized (mLock) {
                    if (mServiceConnection == null) {
                        if (mDefaultSmsAppRequests == null) {
                            mDefaultSmsAppRequests = new IntArray();
                        }
                        mDefaultSmsAppRequests.add(userId);
                        return null;
                    }
                }
                ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
                        mContext, true);
                if (smsComponent != null) {
                    return new String[]{smsComponent.getPackageName()};
                }
                return null;
            }
        });

        // Set a callback for the package manager to query the default dialer app.
        packageManagerInternal.setDialerAppPackagesProvider(
                new PackageManagerInternal.PackagesProvider() {
            @Override
            public String[] getPackages(int userId) {
                synchronized (mLock) {
                    if (mServiceConnection == null) {
                        if (mDefaultDialerAppRequests == null) {
                            mDefaultDialerAppRequests = new IntArray();
                        }
                        mDefaultDialerAppRequests.add(userId);
                        return null;
                    }
                }
                String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
                if (packageName != null) {
                    return new String[]{packageName};
                }
                return null;
            }
        });

        // Set a callback for the package manager to query the default sim call manager.
        packageManagerInternal.setSimCallManagerPackagesProvider(
                new PackageManagerInternal.PackagesProvider() {
            @Override
            public String[] getPackages(int userId) {
                synchronized (mLock) {
                    if (mServiceConnection == null) {
                        if (mDefaultSimCallManagerRequests == null) {
                            mDefaultSimCallManagerRequests = new IntArray();
                        }
                        mDefaultSimCallManagerRequests.add(userId);
                        return null;
                    }
                }
                TelecomManager telecomManager =
                    (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
                PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
                if (phoneAccount != null) {
                    return new String[]{phoneAccount.getComponentName().getPackageName()};
                }
                return null;
            }
        });
    }

    private void registerDefaultAppNotifier() {
        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);

        // Notify the package manager on default app changes
        final Uri defaultSmsAppUri = Settings.Secure.getUriFor(
                Settings.Secure.SMS_DEFAULT_APPLICATION);
        final Uri defaultDialerAppUri = Settings.Secure.getUriFor(
                Settings.Secure.DIALER_DEFAULT_APPLICATION);

        ContentObserver contentObserver = new ContentObserver(
                new Handler(Looper.getMainLooper())) {
            @Override
            public void onChange(boolean selfChange, Uri uri, int userId) {
                if (defaultSmsAppUri.equals(uri)) {
                    ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
                            mContext, true);
                    if (smsComponent != null) {
                        packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
                                smsComponent.getPackageName(), userId);
                    }
                } else if (defaultDialerAppUri.equals(uri)) {
                    String packageName = DefaultDialerManager.getDefaultDialerApplication(
                            mContext);
                    if (packageName != null) {
                        packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
                                packageName, userId);
                    }
                    updateSimCallManagerPermissions(packageManagerInternal, userId);
                }
            }
        };

        mContext.getContentResolver().registerContentObserver(defaultSmsAppUri,
                false, contentObserver, UserHandle.USER_ALL);
        mContext.getContentResolver().registerContentObserver(defaultDialerAppUri,
                false, contentObserver, UserHandle.USER_ALL);
    }


    private void registerCarrierConfigChangedReceiver() {
        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
                    for (int userId : UserManagerService.getInstance().getUserIds()) {
                        updateSimCallManagerPermissions(packageManagerInternal, userId);
                    }
                }
            }
        };

        mContext.registerReceiverAsUser(receiver, UserHandle.ALL,
            new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED), null, null);
    }

    private void updateSimCallManagerPermissions(PackageManagerInternal packageManagerInternal,
            int userId) {
        TelecomManager telecomManager =
            (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
        PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
        if (phoneAccount != null) {
            Slog.i(TAG, "updating sim call manager permissions for userId:" + userId);
            String packageName = phoneAccount.getComponentName().getPackageName();
            packageManagerInternal.grantDefaultPermissionsToDefaultSimCallManager(
                packageName, userId);
        }
    }
}
