/*
 * 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;

import android.Manifest.permission;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.PermissionChecker;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppData;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;

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

/**
 * Internal class for discovering and managing the network scorer/recommendation application.
 *
 * @hide
 */
@VisibleForTesting
public class NetworkScorerAppManager {
    private static final String TAG = "NetworkScorerAppManager";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private final Context mContext;
    private final SettingsFacade mSettingsFacade;

    public NetworkScorerAppManager(Context context) {
      this(context, new SettingsFacade());
    }

    @VisibleForTesting
    public NetworkScorerAppManager(Context context, SettingsFacade settingsFacade) {
        mContext = context;
        mSettingsFacade = settingsFacade;
    }

    /**
     * Returns the list of available scorer apps. The list will be empty if there are
     * no valid scorers.
     */
    @VisibleForTesting
    public List<NetworkScorerAppData> getAllValidScorers() {
        if (VERBOSE) Log.v(TAG, "getAllValidScorers()");
        final PackageManager pm = mContext.getPackageManager();
        final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
        final List<ResolveInfo> resolveInfos =
                pm.queryIntentServices(serviceIntent, PackageManager.GET_META_DATA);
        if (resolveInfos == null || resolveInfos.isEmpty()) {
            if (DEBUG) Log.d(TAG, "Found 0 Services able to handle " + serviceIntent);
            return Collections.emptyList();
        }

        List<NetworkScorerAppData> appDataList = new ArrayList<>();
        for (int i = 0; i < resolveInfos.size(); i++) {
            final ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
            if (hasPermissions(serviceInfo.applicationInfo.uid, serviceInfo.packageName)) {
                if (VERBOSE) {
                    Log.v(TAG, serviceInfo.packageName + " is a valid scorer/recommender.");
                }
                final ComponentName serviceComponentName =
                        new ComponentName(serviceInfo.packageName, serviceInfo.name);
                final String serviceLabel = getRecommendationServiceLabel(serviceInfo, pm);
                final ComponentName useOpenWifiNetworksActivity =
                        findUseOpenWifiNetworksActivity(serviceInfo);
                final String networkAvailableNotificationChannelId =
                        getNetworkAvailableNotificationChannelId(serviceInfo);
                appDataList.add(
                        new NetworkScorerAppData(serviceInfo.applicationInfo.uid,
                                serviceComponentName, serviceLabel, useOpenWifiNetworksActivity,
                                networkAvailableNotificationChannelId));
            } else {
                if (VERBOSE) Log.v(TAG, serviceInfo.packageName
                        + " is NOT a valid scorer/recommender.");
            }
        }

        return appDataList;
    }

    @Nullable
    private String getRecommendationServiceLabel(ServiceInfo serviceInfo, PackageManager pm) {
        if (serviceInfo.metaData != null) {
            final String label = serviceInfo.metaData
                    .getString(NetworkScoreManager.RECOMMENDATION_SERVICE_LABEL_META_DATA);
            if (!TextUtils.isEmpty(label)) {
                return label;
            }
        }
        CharSequence label = serviceInfo.loadLabel(pm);
        return label == null ? null : label.toString();
    }

    @Nullable
    private ComponentName findUseOpenWifiNetworksActivity(ServiceInfo serviceInfo) {
        if (serviceInfo.metaData == null) {
            if (DEBUG) {
                Log.d(TAG, "No metadata found on " + serviceInfo.getComponentName());
            }
            return null;
        }
        final String useOpenWifiPackage = serviceInfo.metaData
                .getString(NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA);
        if (TextUtils.isEmpty(useOpenWifiPackage)) {
            if (DEBUG) {
                Log.d(TAG, "No use_open_wifi_package metadata found on "
                        + serviceInfo.getComponentName());
            }
            return null;
        }
        final Intent enableUseOpenWifiIntent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE)
                .setPackage(useOpenWifiPackage);
        final ResolveInfo resolveActivityInfo = mContext.getPackageManager()
                .resolveActivity(enableUseOpenWifiIntent, 0 /* flags */);
        if (VERBOSE) {
            Log.d(TAG, "Resolved " + enableUseOpenWifiIntent + " to " + resolveActivityInfo);
        }

        if (resolveActivityInfo != null && resolveActivityInfo.activityInfo != null) {
            return resolveActivityInfo.activityInfo.getComponentName();
        }

        return null;
    }

    @Nullable
    private static String getNetworkAvailableNotificationChannelId(ServiceInfo serviceInfo) {
        if (serviceInfo.metaData == null) {
            if (DEBUG) {
                Log.d(TAG, "No metadata found on " + serviceInfo.getComponentName());
            }
            return null;
        }

        return serviceInfo.metaData.getString(
                NetworkScoreManager.NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID_META_DATA);
    }


    /**
     * Get the application to use for scoring networks.
     *
     * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
     *     selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
     *     it was disabled or uninstalled).
     */
    @Nullable
    @VisibleForTesting
    public NetworkScorerAppData getActiveScorer() {
        final int enabledSetting = getNetworkRecommendationsEnabledSetting();
        if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
            return null;
        }

        return getScorer(getNetworkRecommendationsPackage());
    }

    private NetworkScorerAppData getScorer(String packageName) {
        if (TextUtils.isEmpty(packageName)) {
            return null;
        }

        // Otherwise return the recommendation provider (which may be null).
        List<NetworkScorerAppData> apps = getAllValidScorers();
        for (int i = 0; i < apps.size(); i++) {
            NetworkScorerAppData app = apps.get(i);
            if (app.getRecommendationServicePackageName().equals(packageName)) {
                return app;
            }
        }

        return null;
    }

    private boolean hasPermissions(final int uid, final String packageName) {
        return hasScoreNetworksPermission(packageName)
                && canAccessLocation(uid, packageName);
    }

    private boolean hasScoreNetworksPermission(String packageName) {
        final PackageManager pm = mContext.getPackageManager();
        return pm.checkPermission(permission.SCORE_NETWORKS, packageName)
                == PackageManager.PERMISSION_GRANTED;
    }

    private boolean canAccessLocation(int uid, String packageName) {
        return isLocationModeEnabled() && PermissionChecker.checkPermissionForPreflight(mContext,
                permission.ACCESS_COARSE_LOCATION, PermissionChecker.PID_UNKNOWN, uid, packageName)
                == PermissionChecker.PERMISSION_GRANTED;
    }

    private boolean isLocationModeEnabled() {
        return mSettingsFacade.getSecureInt(mContext, Settings.Secure.LOCATION_MODE,
                Settings.Secure.LOCATION_MODE_OFF) != Settings.Secure.LOCATION_MODE_OFF;
    }

    /**
     * Set the specified package as the default scorer application.
     *
     * <p>The caller must have permission to write to {@link Settings.Global}.
     *
     * @param packageName the packageName of the new scorer to use. If null, scoring will be forced
     *                    off, otherwise the scorer will only be set if it is a valid scorer
     *                    application.
     * @return true if the package was a valid scorer (including <code>null</code>) and now
     *         represents the active scorer, false otherwise.
     */
    @VisibleForTesting
    public boolean setActiveScorer(String packageName) {
        final String oldPackageName = getNetworkRecommendationsPackage();

        if (TextUtils.equals(oldPackageName, packageName)) {
            // No change.
            return true;
        }

        if (TextUtils.isEmpty(packageName)) {
            Log.i(TAG, "Network scorer forced off, was: " + oldPackageName);
            setNetworkRecommendationsPackage(null);
            setNetworkRecommendationsEnabledSetting(
                    NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
            return true;
        }

        // We only make the change if the new package is valid.
        if (getScorer(packageName) != null) {
            Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
            setNetworkRecommendationsPackage(packageName);
            setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
            return true;
        } else {
            Log.w(TAG, "Requested network scorer is not valid: " + packageName);
            return false;
        }
    }

    /**
     * Ensures the {@link Settings.Global#NETWORK_RECOMMENDATIONS_PACKAGE} setting points to a valid
     * package and {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} is consistent.
     *
     * If {@link Settings.Global#NETWORK_RECOMMENDATIONS_PACKAGE} doesn't point to a valid package
     * then it will be reverted to the default package specified by
     * {@link R.string#config_defaultNetworkRecommendationProviderPackage}. If the default package
     * is no longer valid then {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} will be set
     * to <code>0</code> (disabled).
     */
    @VisibleForTesting
    public void updateState() {
        final int enabledSetting = getNetworkRecommendationsEnabledSetting();
        if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
            // Don't change anything if it's forced off.
            if (DEBUG) Log.d(TAG, "Recommendations forced off.");
            return;
        }

        // First, see if the current package is still valid. If so, then we can exit early.
        final String currentPackageName = getNetworkRecommendationsPackage();
        if (getScorer(currentPackageName) != null) {
            if (VERBOSE) Log.v(TAG, currentPackageName + " is the active scorer.");
            setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
            return;
        }

        int newEnabledSetting = NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF;
        // the active scorer isn't valid, revert to the default if it's different and valid
        final String defaultPackageName = getDefaultPackageSetting();
        if (!TextUtils.equals(currentPackageName, defaultPackageName)
                && getScorer(defaultPackageName) != null) {
            if (DEBUG) {
                Log.d(TAG, "Defaulting the network recommendations app to: "
                        + defaultPackageName);
            }
            setNetworkRecommendationsPackage(defaultPackageName);
            newEnabledSetting = NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON;
        }

        setNetworkRecommendationsEnabledSetting(newEnabledSetting);
    }

    /**
     * Migrates the NETWORK_SCORER_APP Setting to the USE_OPEN_WIFI_PACKAGE Setting.
     */
    @VisibleForTesting
    public void migrateNetworkScorerAppSettingIfNeeded() {
        final String scorerAppPkgNameSetting =
                mSettingsFacade.getString(mContext, Settings.Global.NETWORK_SCORER_APP);
        if (TextUtils.isEmpty(scorerAppPkgNameSetting)) {
            // Early exit, nothing to do.
            return;
        }

        final NetworkScorerAppData currentAppData = getActiveScorer();
        if (currentAppData == null) {
            // Don't touch anything until we have an active scorer to work with.
            return;
        }

        if (DEBUG) {
            Log.d(TAG, "Migrating Settings.Global.NETWORK_SCORER_APP "
                    + "(" + scorerAppPkgNameSetting + ")...");
        }

        // If the new (useOpenWifi) Setting isn't set and the old Setting's value matches the
        // new metadata value then update the new Setting with the old value. Otherwise it's a
        // mismatch so we shouldn't enable the Setting automatically.
        final ComponentName enableUseOpenWifiActivity =
                currentAppData.getEnableUseOpenWifiActivity();
        final String useOpenWifiSetting =
                mSettingsFacade.getString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE);
        if (TextUtils.isEmpty(useOpenWifiSetting)
                && enableUseOpenWifiActivity != null
                && scorerAppPkgNameSetting.equals(enableUseOpenWifiActivity.getPackageName())) {
            mSettingsFacade.putString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE,
                    scorerAppPkgNameSetting);
            if (DEBUG) {
                Log.d(TAG, "Settings.Global.USE_OPEN_WIFI_PACKAGE set to "
                        + "'" + scorerAppPkgNameSetting + "'.");
            }
        }

        // Clear out the old setting so we don't run through the migration code again.
        mSettingsFacade.putString(mContext, Settings.Global.NETWORK_SCORER_APP, null);
        if (DEBUG) {
            Log.d(TAG, "Settings.Global.NETWORK_SCORER_APP migration complete.");
            final String setting =
                    mSettingsFacade.getString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE);
            Log.d(TAG, "Settings.Global.USE_OPEN_WIFI_PACKAGE is: '" + setting + "'.");
        }
    }

    private String getDefaultPackageSetting() {
        return mContext.getResources().getString(
                R.string.config_defaultNetworkRecommendationProviderPackage);
    }

    private String getNetworkRecommendationsPackage() {
        return mSettingsFacade.getString(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE);
    }

    private void setNetworkRecommendationsPackage(String packageName) {
        mSettingsFacade.putString(mContext,
                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, packageName);
        if (VERBOSE) {
            Log.d(TAG, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE + " set to " + packageName);
        }
    }

    private int getNetworkRecommendationsEnabledSetting() {
        return mSettingsFacade.getInt(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
    }

    private void setNetworkRecommendationsEnabledSetting(int value) {
        mSettingsFacade.putInt(mContext,
                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, value);
        if (VERBOSE) {
            Log.d(TAG, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED + " set to " + value);
        }
    }

    /**
     * Wrapper around Settings to make testing easier.
     */
    public static class SettingsFacade {
        public boolean putString(Context context, String name, String value) {
            return Settings.Global.putString(context.getContentResolver(), name, value);
        }

        public String getString(Context context, String name) {
            return Settings.Global.getString(context.getContentResolver(), name);
        }

        public boolean putInt(Context context, String name, int value) {
            return Settings.Global.putInt(context.getContentResolver(), name, value);
        }

        public int getInt(Context context, String name, int defaultValue) {
            return Settings.Global.getInt(context.getContentResolver(), name, defaultValue);
        }

        public int getSecureInt(Context context, String name, int defaultValue) {
            final ContentResolver cr = context.getContentResolver();
            return Settings.Secure.getIntForUser(cr, name, defaultValue, cr.getUserId());
        }
    }
}
