com.android.usbtuner.DvbDeviceAccessor.java Source code

Java tutorial

Introduction

Here is the source code for com.android.usbtuner.DvbDeviceAccessor.java

Source

/*
 * Copyright (C) 2015 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.usbtuner;

import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.media.tv.TvInputInfo;
import android.media.tv.TvInputManager;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.os.BuildCompat;
import android.util.Log;

import com.android.tv.common.SoftPreconditions;
import com.android.tv.common.feature.CommonFeatures;
import com.android.tv.common.recording.RecordingCapability;
import com.android.usbtuner.tvinput.UsbTunerTvInputService;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Provides with the file descriptors to access DVB device.
 */
public class DvbDeviceAccessor {
    private static final String TAG = "DvbDeviceAccessor";

    @IntDef({ DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_FRONTEND })
    @Retention(RetentionPolicy.SOURCE)
    public @interface DvbDevice {
    }

    public static final int DVB_DEVICE_DEMUX = 0; // TvInputManager.DVB_DEVICE_DEMUX;
    public static final int DVB_DEVICE_DVR = 1; // TvInputManager.DVB_DEVICE_DVR;
    public static final int DVB_DEVICE_FRONTEND = 2; // TvInputManager.DVB_DEVICE_FRONTEND;

    private static Method sGetDvbDeviceListMethod;
    private static Method sOpenDvbDeviceMethod;

    private final TvInputManager mTvInputManager;

    static {
        try {
            Class tvInputManagerClass = Class.forName("android.media.tv.TvInputManager");
            Class dvbDeviceInfoClass = Class.forName("android.media.tv.DvbDeviceInfo");
            sGetDvbDeviceListMethod = tvInputManagerClass.getDeclaredMethod("getDvbDeviceList");
            sGetDvbDeviceListMethod.setAccessible(true);
            sOpenDvbDeviceMethod = tvInputManagerClass.getDeclaredMethod("openDvbDevice", dvbDeviceInfoClass,
                    Integer.TYPE);
            sOpenDvbDeviceMethod.setAccessible(true);
        } catch (ClassNotFoundException e) {
            Log.e(TAG, "Couldn't find class", e);
        } catch (NoSuchMethodException e) {
            Log.e(TAG, "Couldn't find method", e);
        }
    }

    public DvbDeviceAccessor(Context context) {
        mTvInputManager = (TvInputManager) context.getSystemService(context.TV_INPUT_SERVICE);
    }

    public List<DvbDeviceInfoWrapper> getDvbDeviceList() {
        try {
            List<DvbDeviceInfoWrapper> wrapperList = new ArrayList<>();
            List dvbDeviceInfoList = (List) sGetDvbDeviceListMethod.invoke(mTvInputManager);
            for (Object dvbDeviceInfo : dvbDeviceInfoList) {
                wrapperList.add(new DvbDeviceInfoWrapper(dvbDeviceInfo));
            }
            Collections.sort(wrapperList);
            return wrapperList;
        } catch (IllegalAccessException e) {
            Log.e(TAG, "Couldn't access", e);
        } catch (InvocationTargetException e) {
            Log.e(TAG, "Couldn't invoke", e);
        }
        return null;
    }

    public boolean isDvbDeviceAvailable() {
        try {
            List dvbDeviceInfoList = (List) sGetDvbDeviceListMethod.invoke(mTvInputManager);
            return (!dvbDeviceInfoList.isEmpty());
        } catch (IllegalAccessException e) {
            Log.e(TAG, "Couldn't access", e);
        } catch (InvocationTargetException e) {
            Log.e(TAG, "Couldn't invoke", e);
        }
        return false;
    }

    public ParcelFileDescriptor openDvbDevice(DvbDeviceInfoWrapper deviceInfo, @DvbDevice int device) {
        try {
            return (ParcelFileDescriptor) sOpenDvbDeviceMethod.invoke(mTvInputManager,
                    deviceInfo.getDvbDeviceInfo(), device);
        } catch (IllegalAccessException e) {
            Log.e(TAG, "Couldn't access", e);
        } catch (InvocationTargetException e) {
            Log.e(TAG, "Couldn't invoke", e);
        }
        return null;
    }

    /**
     * Returns the current recording capability for USB tuner.
     * @param inputId the input id to use.
     */
    public RecordingCapability getRecordingCapability(String inputId) {
        List<DvbDeviceInfoWrapper> deviceList = getDvbDeviceList();
        // TODO(DVR) implement accurate capabilities and updating values when needed.
        return RecordingCapability.builder().setInputId(inputId).setMaxConcurrentPlayingSessions(1)
                .setMaxConcurrentTunedSessions(deviceList.size())
                .setMaxConcurrentSessionsOfAllTypes(deviceList.size() + 1).build();
    }

    @Nullable
    @TargetApi(Build.VERSION_CODES.N)
    public TvInputInfo buildTvInputInfo(Context context) {
        List<DvbDeviceInfoWrapper> deviceList = getDvbDeviceList();
        TvInputInfo.Builder builder = new TvInputInfo.Builder(context,
                new ComponentName(context, UsbTunerTvInputService.class));
        if (deviceList.size() > 0) {
            return builder.setCanRecord(CommonFeatures.DVR.isEnabled(context) && BuildCompat.isAtLeastN())
                    .setTunerCount(deviceList.size()).build();
        } else {
            return null;
        }
    }

    public static class DvbDeviceInfoWrapper implements Comparable<DvbDeviceInfoWrapper> {
        private static Method sGetAdapterIdMethod;
        private static Method sGetDeviceIdMethod;
        private final Object mDvbDeviceInfo;
        private final int mAdapterId;
        private final int mDeviceId;
        private final long mId;

        static {
            try {
                Class dvbDeviceInfoClass = Class.forName("android.media.tv.DvbDeviceInfo");
                sGetAdapterIdMethod = dvbDeviceInfoClass.getDeclaredMethod("getAdapterId");
                sGetAdapterIdMethod.setAccessible(true);
                sGetDeviceIdMethod = dvbDeviceInfoClass.getDeclaredMethod("getDeviceId");
                sGetDeviceIdMethod.setAccessible(true);
            } catch (ClassNotFoundException e) {
                Log.e(TAG, "Couldn't find class", e);
            } catch (NoSuchMethodException e) {
                Log.e(TAG, "Couldn't find method", e);
            }
        }

        public DvbDeviceInfoWrapper(Object dvbDeviceInfo) {
            mDvbDeviceInfo = dvbDeviceInfo;
            mAdapterId = initAdapterId();
            mDeviceId = initDeviceId();
            mId = (((long) getAdapterId()) << 32) | (getDeviceId() & 0xffffffffL);
        }

        public long getId() {
            return mId;
        }

        public int getAdapterId() {
            return mAdapterId;
        }

        private int initAdapterId() {
            try {
                return (int) sGetAdapterIdMethod.invoke(mDvbDeviceInfo);
            } catch (InvocationTargetException e) {
                Log.e(TAG, "Couldn't invoke", e);
            } catch (IllegalAccessException e) {
                Log.e(TAG, "Couldn't access", e);
            }
            return -1;
        }

        public int getDeviceId() {
            return mDeviceId;
        }

        private int initDeviceId() {
            try {
                return (int) sGetDeviceIdMethod.invoke(mDvbDeviceInfo);
            } catch (InvocationTargetException e) {
                Log.e(TAG, "Couldn't invoke", e);
            } catch (IllegalAccessException e) {
                Log.e(TAG, "Couldn't access", e);
            }
            return -1;
        }

        public Object getDvbDeviceInfo() {
            return mDvbDeviceInfo;
        }

        @Override
        public int compareTo(@NonNull DvbDeviceInfoWrapper another) {
            if (getAdapterId() != another.getAdapterId()) {
                return getAdapterId() - another.getAdapterId();
            }
            return getDeviceId() - another.getDeviceId();
        }

        @Override
        public String toString() {
            return String.format("DvbDeviceInfo {adapterId: %d, deviceId: %d}", getAdapterId(), getDeviceId());
        }
    }
}