/*
 * 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.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
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) {
        final PackageManager pm = mContext.getPackageManager();
        final AppOpsManager appOpsManager =
                (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        return isLocationModeEnabled()
                && pm.checkPermission(permission.ACCESS_COARSE_LOCATION, packageName)
                == PackageManager.PERMISSION_GRANTED
                && appOpsManager.noteOp(AppOpsManager.OP_COARSE_LOCATION, uid, packageName)
                == AppOpsManager.MODE_ALLOWED;
    }

    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) {
            return Settings.Secure.getInt(context.getContentResolver(), name, defaultValue);
        }
    }
}
