/*
 * Copyright (C) 2016 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 android.car.usb.handler;

import static android.content.pm.PackageManager.PERMISSION_GRANTED;

import android.Manifest;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.XmlResourceParser;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import com.android.internal.util.XmlUtils;

import org.xmlpull.v1.XmlPullParser;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/** Resolves supported handlers for USB device. */
public final class UsbDeviceHandlerResolver {

    private static final String TAG = UsbDeviceHandlerResolver.class.getSimpleName();
    private static final boolean LOCAL_LOGD = true;

    private static final String AOAP_HANDLE_PERMISSION =
            "android.car.permission.CAR_HANDLE_USB_AOAP_DEVICE";

    /**
     * Callbacks for device resolver.
     */
    public interface UsbDeviceHandlerResolverCallback {
        /** Handlers are resolved */
        void onHandlersResolveCompleted(
                UsbDevice device, List<UsbDeviceSettings> availableSettings);
        /** Device was dispatched */
        void onDeviceDispatched();
    }

    private final UsbManager mUsbManager;
    private final PackageManager mPackageManager;
    private final UsbDeviceHandlerResolverCallback mDeviceCallback;
    private final Context mContext;
    private final HandlerThread mHandlerThread;
    private final UsbDeviceResolverHandler mHandler;
    private final AoapServiceManager mAoapServiceManager;

    public UsbDeviceHandlerResolver(UsbManager manager, Context context,
            UsbDeviceHandlerResolverCallback deviceListener) {
        mUsbManager = manager;
        mContext = context;
        mDeviceCallback = deviceListener;
        mHandlerThread = new HandlerThread(TAG);
        mHandlerThread.start();
        mHandler = new UsbDeviceResolverHandler(mHandlerThread.getLooper());
        mPackageManager = context.getPackageManager();
        mAoapServiceManager = new AoapServiceManager(mContext.getApplicationContext());
    }

    /**
     * Releases current object.
     */
    public void release() {
        if (mHandlerThread != null) {
            mHandlerThread.quitSafely();
        }
    }

    /**
     * Resolves handlers for USB device.
     */
    public void resolve(UsbDevice device) {
        mHandler.requestResolveHandlers(device);
    }

    /**
     * Dispatches device to component.
     */
    public boolean dispatch(UsbDevice device, ComponentName component, boolean inAoap) {
        if (LOCAL_LOGD) {
            Log.d(TAG, "dispatch: " + device + " component: " + component + " inAoap: " + inAoap);
        }

        ActivityInfo activityInfo;
        try {
            activityInfo = mPackageManager.getActivityInfo(component, PackageManager.GET_META_DATA);
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Activity not found: " + component);
            return false;
        }

        Intent intent = createDeviceAttachedIntent(device);
        if (inAoap) {
            if (AoapInterface.isDeviceInAoapMode(device)) {
                mDeviceCallback.onDeviceDispatched();
            } else {
                UsbDeviceFilter filter =
                        packageMatches(activityInfo, intent.getAction(), device, true);

                if (filter != null) {
                    mHandlerThread.getThreadHandler().post(() -> {
                        if (mAoapServiceManager.canSwitchDeviceToAoap(device,
                                ComponentName.unflattenFromString(filter.mAoapService))) {
                            requestAoapSwitch(device, filter);
                        } else {
                            Log.i(TAG, "Ignore AOAP switch for device " + device
                                    + " handled by " + filter.mAoapService);
                        }
                    });
                    return true;
                }
            }
        }

        intent.setComponent(component);
        mUsbManager.grantPermission(device, activityInfo.applicationInfo.uid);

        mContext.startActivity(intent);
        mHandler.requestCompleteDeviceDispatch();
        return true;
    }

    private static Intent createDeviceAttachedIntent(UsbDevice device) {
        Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        intent.putExtra(UsbManager.EXTRA_DEVICE, device);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        return intent;
    }

    private void doHandleResolveHandlers(UsbDevice device) {
        if (LOCAL_LOGD) {
            Log.d(TAG, "doHandleResolveHandlers: " + device);
        }

        Intent intent = createDeviceAttachedIntent(device);
        List<UsbHandlerPackage> matches = getDeviceMatches(device, intent, false);
        if (LOCAL_LOGD) {
            Log.d(TAG, "matches size: " + matches.size());
        }
        List<UsbDeviceSettings> settings = new ArrayList<>();
        for (UsbHandlerPackage pkg : matches) {
            settings.add(createSettings(device, pkg));
        }

        UsbDeviceConnection devConnection = UsbUtil.openConnection(mUsbManager, device);
        if (devConnection != null && AoapInterface.isSupported(mContext, device, devConnection)) {
            for (UsbHandlerPackage pkg : getDeviceMatches(device, intent, true)) {
                if (mAoapServiceManager.isDeviceSupported(device, pkg.mAoapService)) {
                    settings.add(createSettings(device, pkg));
                }
            }
        }

        deviceProbingComplete(device, settings);
    }

    private UsbDeviceSettings createSettings(UsbDevice device, UsbHandlerPackage pkg) {
        UsbDeviceSettings settings = UsbDeviceSettings.constructSettings(device);
        settings.setHandler(pkg.mActivity);
        settings.setAoap(pkg.mAoapService != null);
        return settings;
    }

    private void requestAoapSwitch(UsbDevice device, UsbDeviceFilter filter) {
        UsbDeviceConnection connection = UsbUtil.openConnection(mUsbManager, device);
        if (connection == null) {
            Log.e(TAG, "Failed to connect to usb device.");
            return;
        }
        try {
            UsbUtil.sendAoapAccessoryStart(
                    connection,
                    filter.mAoapManufacturer,
                    filter.mAoapModel,
                    filter.mAoapDescription,
                    filter.mAoapVersion,
                    filter.mAoapUri,
                    filter.mAoapSerial);
        } catch (IOException e) {
            Log.w(TAG, "Failed to switch device into AOAP mode", e);
        }
        connection.close();
    }

    private void deviceProbingComplete(UsbDevice device, List<UsbDeviceSettings> settings) {
        if (LOCAL_LOGD) {
            Log.d(TAG, "deviceProbingComplete");
        }
        mDeviceCallback.onHandlersResolveCompleted(device, settings);
    }

    private List<UsbHandlerPackage> getDeviceMatches(
            UsbDevice device, Intent intent, boolean forAoap) {
        List<UsbHandlerPackage> matches = new ArrayList<>();
        List<ResolveInfo> resolveInfos =
                mPackageManager.queryIntentActivities(intent, PackageManager.GET_META_DATA);
        for (ResolveInfo resolveInfo : resolveInfos) {
            final String packageName = resolveInfo.activityInfo.packageName;
            if (forAoap && !hasAoapPermission(packageName)) {
                Log.w(TAG, "Package " + packageName + " does not hold "
                        + AOAP_HANDLE_PERMISSION + " permission. Ignore the package.");
                continue;
            }

            UsbDeviceFilter filter = packageMatches(resolveInfo.activityInfo,
                    intent.getAction(), device, forAoap);
            if (filter != null) {
                ActivityInfo ai = resolveInfo.activityInfo;
                ComponentName activity = new ComponentName(ai.packageName, ai.name);
                ComponentName aoapService = filter.mAoapService == null
                        ? null : ComponentName.unflattenFromString(filter.mAoapService);

                if (aoapService != null && !checkServiceRequiresPermission(aoapService)) {
                    continue;
                }

                if (aoapService != null || !forAoap) {
                    matches.add(new UsbHandlerPackage(activity, aoapService));
                }
            }
        }
        return matches;
    }

    private boolean checkServiceRequiresPermission(ComponentName serviceName) {
        Intent intent = new Intent();
        intent.setComponent(serviceName);
        boolean found = false;
        for (ResolveInfo info : mPackageManager.queryIntentServices(intent, 0)) {
            if (info.serviceInfo != null) {
                found = true;
                if ((Manifest.permission.MANAGE_USB.equals(info.serviceInfo.permission))) {
                    return true;
                }
            }
        }
        if (found) {
            Log.w(TAG, "Component " + serviceName + " must be protected with "
                    + Manifest.permission.MANAGE_USB + " permission");
        } else {
            Log.w(TAG, "Component " + serviceName + " not found");
        }
        return false;
    }

    private boolean hasAoapPermission(String packageName) {
        return mPackageManager
                .checkPermission(AOAP_HANDLE_PERMISSION, packageName) == PERMISSION_GRANTED;
    }

    private UsbDeviceFilter packageMatches(ActivityInfo ai, String metaDataName, UsbDevice device,
            boolean forAoap) {
        if (LOCAL_LOGD) {
            Log.d(TAG, "packageMatches ai: " + ai + "metaDataName: " + metaDataName + " forAoap: "
                    + forAoap);
        }
        String filterTagName = forAoap ? "usb-aoap-accessory" : "usb-device";
        try (XmlResourceParser parser = ai.loadXmlMetaData(mPackageManager, metaDataName)) {
            if (parser == null) {
                Log.w(TAG, "no meta-data for " + ai);
                return null;
            }

            XmlUtils.nextElement(parser);
            while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
                String tagName = parser.getName();
                if (device != null && filterTagName.equals(tagName)) {
                    UsbDeviceFilter filter = UsbDeviceFilter.read(parser, forAoap);
                    if (forAoap || filter.matches(device)) {
                        return filter;
                    }
                }
                XmlUtils.nextElement(parser);
            }
        } catch (Exception e) {
            Log.w(TAG, "Unable to load component info " + ai.toString(), e);
        }
        return null;
    }

    private class UsbDeviceResolverHandler extends Handler {
        private static final int MSG_RESOLVE_HANDLERS = 0;
        private static final int MSG_COMPLETE_DISPATCH = 3;

        private UsbDeviceResolverHandler(Looper looper) {
            super(looper);
        }

        void requestResolveHandlers(UsbDevice device) {
            Message msg = obtainMessage(MSG_RESOLVE_HANDLERS, device);
            sendMessage(msg);
        }

        void requestCompleteDeviceDispatch() {
            sendEmptyMessage(MSG_COMPLETE_DISPATCH);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_RESOLVE_HANDLERS:
                    doHandleResolveHandlers((UsbDevice) msg.obj);
                    break;
                case MSG_COMPLETE_DISPATCH:
                    mDeviceCallback.onDeviceDispatched();
                    break;
                default:
                    Log.w(TAG, "Unsupported message: " + msg);
            }
        }
    }

    private static class UsbHandlerPackage {
        final ComponentName mActivity;
        final @Nullable ComponentName mAoapService;

        UsbHandlerPackage(ComponentName activity, @Nullable ComponentName aoapService) {
            mActivity = activity;
            mAoapService = aoapService;
        }
    }
}
