/*
 * Copyright (C) 2013 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.settings.location;

import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.location.SettingInjectorService;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.preference.Preference;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.IconDrawableFactory;
import android.util.Log;
import android.util.Xml;

import com.android.settings.widget.AppPreference;
import com.android.settings.widget.RestrictedAppPreference;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Adds the preferences specified by the {@link InjectedSetting} objects to a preference group.
 *
 * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}. We do not use that
 * class directly because it is not a good match for our use case: we do not need the caching, and
 * so do not want the additional resource hit at app install/upgrade time; and we would have to
 * suppress the tie-breaking between multiple services reporting settings with the same name.
 * Code-sharing would require extracting {@link
 * android.content.pm.RegisteredServicesCache#parseServiceAttributes(android.content.res.Resources,
 * String, android.util.AttributeSet)} into an interface, which didn't seem worth it.
 */
class SettingsInjector {
    static final String TAG = "SettingsInjector";

    /**
     * If reading the status of a setting takes longer than this, we go ahead and start reading
     * the next setting.
     */
    private static final long INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS = 1000;

    /**
     * {@link Message#what} value for starting to load status values
     * in case we aren't already in the process of loading them.
     */
    private static final int WHAT_RELOAD = 1;

    /**
     * {@link Message#what} value sent after receiving a status message.
     */
    private static final int WHAT_RECEIVED_STATUS = 2;

    /**
     * {@link Message#what} value sent after the timeout waiting for a status message.
     */
    private static final int WHAT_TIMEOUT = 3;

    private final Context mContext;

    /**
     * The settings that were injected
     */
    private final Set<Setting> mSettings;

    private final Handler mHandler;

    public SettingsInjector(Context context) {
        mContext = context;
        mSettings = new HashSet<Setting>();
        mHandler = new StatusLoadingHandler();
    }

    /**
     * Returns a list for a profile with one {@link InjectedSetting} object for each
     * {@link android.app.Service} that responds to
     * {@link SettingInjectorService#ACTION_SERVICE_INTENT} and provides the expected setting
     * metadata.
     *
     * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
     *
     * TODO: unit test
     */
    private List<InjectedSetting> getSettings(final UserHandle userHandle) {
        PackageManager pm = mContext.getPackageManager();
        Intent intent = new Intent(SettingInjectorService.ACTION_SERVICE_INTENT);

        final int profileId = userHandle.getIdentifier();
        List<ResolveInfo> resolveInfos =
                pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, profileId);
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Found services for profile id " + profileId + ": " + resolveInfos);
        }
        List<InjectedSetting> settings = new ArrayList<InjectedSetting>(resolveInfos.size());
        for (ResolveInfo resolveInfo : resolveInfos) {
            try {
                InjectedSetting setting = parseServiceInfo(resolveInfo, userHandle, pm);
                if (setting == null) {
                    Log.w(TAG, "Unable to load service info " + resolveInfo);
                } else {
                    settings.add(setting);
                }
            } catch (XmlPullParserException e) {
                Log.w(TAG, "Unable to load service info " + resolveInfo, e);
            } catch (IOException e) {
                Log.w(TAG, "Unable to load service info " + resolveInfo, e);
            }
        }
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Loaded settings for profile id " + profileId + ": " + settings);
        }

        return settings;
    }

    /**
     * Returns the settings parsed from the attributes of the
     * {@link SettingInjectorService#META_DATA_NAME} tag, or null.
     *
     * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
     */
    private static InjectedSetting parseServiceInfo(ResolveInfo service, UserHandle userHandle,
            PackageManager pm) throws XmlPullParserException, IOException {

        ServiceInfo si = service.serviceInfo;
        ApplicationInfo ai = si.applicationInfo;

        if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Ignoring attempt to inject setting from app not in system image: "
                        + service);
                return null;
            }
        }

        XmlResourceParser parser = null;
        try {
            parser = si.loadXmlMetaData(pm, SettingInjectorService.META_DATA_NAME);
            if (parser == null) {
                throw new XmlPullParserException("No " + SettingInjectorService.META_DATA_NAME
                        + " meta-data for " + service + ": " + si);
            }

            AttributeSet attrs = Xml.asAttributeSet(parser);

            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && type != XmlPullParser.START_TAG) {
            }

            String nodeName = parser.getName();
            if (!SettingInjectorService.ATTRIBUTES_NAME.equals(nodeName)) {
                throw new XmlPullParserException("Meta-data does not start with "
                        + SettingInjectorService.ATTRIBUTES_NAME + " tag");
            }

            Resources res = pm.getResourcesForApplicationAsUser(si.packageName,
                    userHandle.getIdentifier());
            return parseAttributes(si.packageName, si.name, userHandle, res, attrs);
        } catch (PackageManager.NameNotFoundException e) {
            throw new XmlPullParserException(
                    "Unable to load resources for package " + si.packageName);
        } finally {
            if (parser != null) {
                parser.close();
            }
        }
    }

    /**
     * Returns an immutable representation of the static attributes for the setting, or null.
     */
    private static InjectedSetting parseAttributes(String packageName, String className,
            UserHandle userHandle, Resources res, AttributeSet attrs) {

        TypedArray sa = res.obtainAttributes(attrs, android.R.styleable.SettingInjectorService);
        try {
            // Note that to help guard against malicious string injection, we do not allow dynamic
            // specification of the label (setting title)
            final String title = sa.getString(android.R.styleable.SettingInjectorService_title);
            final int iconId =
                    sa.getResourceId(android.R.styleable.SettingInjectorService_icon, 0);
            final String settingsActivity =
                    sa.getString(android.R.styleable.SettingInjectorService_settingsActivity);
            final String userRestriction = sa.getString(
                    android.R.styleable.SettingInjectorService_userRestriction);
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "parsed title: " + title + ", iconId: " + iconId
                        + ", settingsActivity: " + settingsActivity);
            }
            return new InjectedSetting.Builder()
                    .setPackageName(packageName)
                    .setClassName(className)
                    .setTitle(title)
                    .setIconId(iconId)
                    .setUserHandle(userHandle)
                    .setSettingsActivity(settingsActivity)
                    .setUserRestriction(userRestriction)
                    .build();
        } finally {
            sa.recycle();
        }
    }

    /**
     * Gets a list of preferences that other apps have injected.
     *
     * @param profileId Identifier of the user/profile to obtain the injected settings for or
     *                  UserHandle.USER_CURRENT for all profiles associated with current user.
     */
    public List<Preference> getInjectedSettings(Context prefContext, final int profileId) {
        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        final List<UserHandle> profiles = um.getUserProfiles();
        ArrayList<Preference> prefs = new ArrayList<>();
        final int profileCount = profiles.size();
        for (int i = 0; i < profileCount; ++i) {
            final UserHandle userHandle = profiles.get(i);
            if (profileId == UserHandle.USER_CURRENT || profileId == userHandle.getIdentifier()) {
                Iterable<InjectedSetting> settings = getSettings(userHandle);
                for (InjectedSetting setting : settings) {
                    Preference pref = addServiceSetting(prefContext, prefs, setting);
                    mSettings.add(new Setting(setting, pref));
                }
            }
        }

        reloadStatusMessages();

        return prefs;
    }

    /**
     * Checks wheteher there is any preference that other apps have injected.
     *
     * @param profileId Identifier of the user/profile to obtain the injected settings for or
     *                  UserHandle.USER_CURRENT for all profiles associated with current user.
     */
    public boolean hasInjectedSettings(final int profileId) {
        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        final List<UserHandle> profiles = um.getUserProfiles();
        final int profileCount = profiles.size();
        for (int i = 0; i < profileCount; ++i) {
            final UserHandle userHandle = profiles.get(i);
            if (profileId == UserHandle.USER_CURRENT || profileId == userHandle.getIdentifier()) {
                Iterable<InjectedSetting> settings = getSettings(userHandle);
                for (InjectedSetting setting : settings) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Reloads the status messages for all the preference items.
     */
    public void reloadStatusMessages() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "reloadingStatusMessages: " + mSettings);
        }
        mHandler.sendMessage(mHandler.obtainMessage(WHAT_RELOAD));
    }

    /**
     * Adds an injected setting to the root.
     */
    private Preference addServiceSetting(Context prefContext, List<Preference> prefs,
            InjectedSetting info) {
        final PackageManager pm = mContext.getPackageManager();
        Drawable appIcon = null;
        try {
            final PackageItemInfo itemInfo = new PackageItemInfo();
            itemInfo.icon = info.iconId;
            itemInfo.packageName = info.packageName;
            final ApplicationInfo appInfo = pm.getApplicationInfo(info.packageName,
                PackageManager.GET_META_DATA);
            appIcon = IconDrawableFactory.newInstance(mContext)
                .getBadgedIcon(itemInfo, appInfo, info.mUserHandle.getIdentifier());
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Can't get ApplicationInfo for " + info.packageName, e);
        }
        Preference pref = TextUtils.isEmpty(info.userRestriction)
                ? new AppPreference(prefContext)
                : new RestrictedAppPreference(prefContext, info.userRestriction);
        pref.setTitle(info.title);
        pref.setSummary(null);
        pref.setIcon(appIcon);
        pref.setOnPreferenceClickListener(new ServiceSettingClickedListener(info));
        prefs.add(pref);
        return pref;
    }

    private class ServiceSettingClickedListener
            implements Preference.OnPreferenceClickListener {
        private InjectedSetting mInfo;

        public ServiceSettingClickedListener(InjectedSetting info) {
            mInfo = info;
        }

        @Override
        public boolean onPreferenceClick(Preference preference) {
            // Activity to start if they click on the preference. Must start in new task to ensure
            // that "android.settings.LOCATION_SOURCE_SETTINGS" brings user back to
            // Settings > Location.
            Intent settingIntent = new Intent();
            settingIntent.setClassName(mInfo.packageName, mInfo.settingsActivity);
            // Sometimes the user may navigate back to "Settings" and launch another different
            // injected setting after one injected setting has been launched.
            //
            // FLAG_ACTIVITY_CLEAR_TOP allows multiple Activities to stack on each other. When
            // "back" button is clicked, the user will navigate through all the injected settings
            // launched before. Such behavior could be quite confusing sometimes.
            //
            // In order to avoid such confusion, we use FLAG_ACTIVITY_CLEAR_TASK, which always clear
            // up all existing injected settings and make sure that "back" button always brings the
            // user back to "Settings" directly.
            settingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            mContext.startActivityAsUser(settingIntent, mInfo.mUserHandle);
            return true;
        }
    }

    /**
     * Loads the setting status values one at a time. Each load starts a subclass of {@link
     * SettingInjectorService}, so to reduce memory pressure we don't want to load too many at
     * once.
     */
    private final class StatusLoadingHandler extends Handler {

        /**
         * Settings whose status values need to be loaded. A set is used to prevent redundant loads.
         */
        private Set<Setting> mSettingsToLoad = new HashSet<Setting>();

        /**
         * Settings that are being loaded now and haven't timed out. In practice this should have
         * zero or one elements.
         */
        private Set<Setting> mSettingsBeingLoaded = new HashSet<Setting>();

        /**
         * Settings that are being loaded but have timed out. If only one setting has timed out, we
         * will go ahead and start loading the next setting so that one slow load won't delay the
         * load of the other settings.
         */
        private Set<Setting> mTimedOutSettings = new HashSet<Setting>();

        private boolean mReloadRequested;

        private StatusLoadingHandler() {
            super(Looper.getMainLooper());
        }
        @Override
        public void handleMessage(Message msg) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "handleMessage start: " + msg + ", " + this);
            }

            // Update state in response to message
            switch (msg.what) {
                case WHAT_RELOAD:
                    mReloadRequested = true;
                    break;
                case WHAT_RECEIVED_STATUS:
                    final Setting receivedSetting = (Setting) msg.obj;
                    receivedSetting.maybeLogElapsedTime();
                    mSettingsBeingLoaded.remove(receivedSetting);
                    mTimedOutSettings.remove(receivedSetting);
                    removeMessages(WHAT_TIMEOUT, receivedSetting);
                    break;
                case WHAT_TIMEOUT:
                    final Setting timedOutSetting = (Setting) msg.obj;
                    mSettingsBeingLoaded.remove(timedOutSetting);
                    mTimedOutSettings.add(timedOutSetting);
                    if (Log.isLoggable(TAG, Log.WARN)) {
                        Log.w(TAG, "Timed out after " + timedOutSetting.getElapsedTime()
                                + " millis trying to get status for: " + timedOutSetting);
                    }
                    break;
                default:
                    Log.wtf(TAG, "Unexpected what: " + msg);
            }

            // Decide whether to load additional settings based on the new state. Start by seeing
            // if we have headroom to load another setting.
            if (mSettingsBeingLoaded.size() > 0 || mTimedOutSettings.size() > 1) {
                // Don't load any more settings until one of the pending settings has completed.
                // To reduce memory pressure, we want to be loading at most one setting (plus at
                // most one timed-out setting) at a time. This means we'll be responsible for
                // bringing in at most two services.
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "too many services already live for " + msg + ", " + this);
                }
                return;
            }

            if (mReloadRequested && mSettingsToLoad.isEmpty() && mSettingsBeingLoaded.isEmpty()
                    && mTimedOutSettings.isEmpty()) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "reloading because idle and reload requesteed " + msg + ", " + this);
                }
                // Reload requested, so must reload all settings
                mSettingsToLoad.addAll(mSettings);
                mReloadRequested = false;
            }

            // Remove the next setting to load from the queue, if any
            Iterator<Setting> iter = mSettingsToLoad.iterator();
            if (!iter.hasNext()) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "nothing left to do for " + msg + ", " + this);
                }
                return;
            }
            Setting setting = iter.next();
            iter.remove();

            // Request the status value
            setting.startService();
            mSettingsBeingLoaded.add(setting);

            // Ensure that if receiving the status value takes too long, we start loading the
            // next value anyway
            Message timeoutMsg = obtainMessage(WHAT_TIMEOUT, setting);
            sendMessageDelayed(timeoutMsg, INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS);

            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "handleMessage end " + msg + ", " + this
                        + ", started loading " + setting);
            }
        }

        @Override
        public String toString() {
            return "StatusLoadingHandler{" +
                    "mSettingsToLoad=" + mSettingsToLoad +
                    ", mSettingsBeingLoaded=" + mSettingsBeingLoaded +
                    ", mTimedOutSettings=" + mTimedOutSettings +
                    ", mReloadRequested=" + mReloadRequested +
                    '}';
        }
    }

    /**
     * Represents an injected setting and the corresponding preference.
     */
    private final class Setting {

        public final InjectedSetting setting;
        public final Preference preference;
        public long startMillis;

        private Setting(InjectedSetting setting, Preference preference) {
            this.setting = setting;
            this.preference = preference;
        }

        @Override
        public String toString() {
            return "Setting{" +
                    "setting=" + setting +
                    ", preference=" + preference +
                    '}';
        }

        /**
         * Returns true if they both have the same {@link #setting} value. Ignores mutable
         * {@link #preference} and {@link #startMillis} so that it's safe to use in sets.
         */
        @Override
        public boolean equals(Object o) {
            return this == o || o instanceof Setting && setting.equals(((Setting) o).setting);
        }

        @Override
        public int hashCode() {
            return setting.hashCode();
        }

        /**
         * Starts the service to fetch for the current status for the setting, and updates the
         * preference when the service replies.
         */
        public void startService() {
            final ActivityManager am = (ActivityManager)
                    mContext.getSystemService(Context.ACTIVITY_SERVICE);
            if (!am.isUserRunning(setting.mUserHandle.getIdentifier())) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "Cannot start service as user "
                            + setting.mUserHandle.getIdentifier() + " is not running");
                }
                return;
            }
            Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Bundle bundle = msg.getData();
                    boolean enabled = bundle.getBoolean(SettingInjectorService.ENABLED_KEY, true);
                    if (Log.isLoggable(TAG, Log.DEBUG)) {
                        Log.d(TAG, setting + ": received " + msg + ", bundle: " + bundle);
                    }
                    preference.setSummary(null);
                    preference.setEnabled(enabled);
                    mHandler.sendMessage(
                            mHandler.obtainMessage(WHAT_RECEIVED_STATUS, Setting.this));
                }
            };
            Messenger messenger = new Messenger(handler);

            Intent intent = setting.getServiceIntent();
            intent.putExtra(SettingInjectorService.MESSENGER_KEY, messenger);

            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, setting + ": sending update intent: " + intent
                        + ", handler: " + handler);
                startMillis = SystemClock.elapsedRealtime();
            } else {
                startMillis = 0;
            }

            // Start the service, making sure that this is attributed to the user associated with
            // the setting rather than the system user.
            mContext.startServiceAsUser(intent, setting.mUserHandle);
        }

        public long getElapsedTime() {
            long end = SystemClock.elapsedRealtime();
            return end - startMillis;
        }

        public void maybeLogElapsedTime() {
            if (Log.isLoggable(TAG, Log.DEBUG) && startMillis != 0) {
                long elapsed = getElapsedTime();
                Log.d(TAG, this + " update took " + elapsed + " millis");
            }
        }
    }
}
