android TIF启动流程--转载

TIF是Tv Input Framework的简称,是Android在5.0后加入的tv框架,为了支持android tv功能。

1 TvInputManagerService启动流程
TvInputManagerService在TIF框架结构中扮演Java service层的角色,向java api提供接口实现。
在SystemServer的Main  Thread里面,执行run函数时,回去启动各种services :
startBootstrapServices();
startCoreServices();
startOtherServices();
在startOtherServices()函数里会去启动TvInputManagerService服务:
 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)) {
        mSystemServiceManager.startService(TvInputManagerService.class);
}
支持TIF,平台需要配置feature PackageManager.FEATURE_LIVE_TV,否则无法启动TvInputManagerService.
startService函数会做下面几件事情:
1)TvInputManagerService注册到SystemService
 // Register it.
mServices.add(service);

2)通过反射获取TvInputManagerService实例
 public TvInputManagerService(Context context) {
        super(context);
 
        mContext = context;
        mWatchLogHandler = new WatchLogHandler(mContext.getContentResolver(),
                IoThread.get().getLooper());
        mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener());
 
        synchronized (mLock) {
            getOrCreateUserStateLocked(mCurrentUserId);
        }
    }
主要实例化TvInputHardwareManager,TvInputHardwareManager辅助TvInputManagerService管理Tv Input device,包含Tv Input Device Status变化等。
WatchLogHandler是一个Handler,用于处理watch事件,对于这个handler的解释如下:
 // There are only two kinds of watch events that can happen on the system:
        // 1. The current TV input session is tuned to a new channel.
        // 2. The session is released for some reason.
看实现是有一个db去保存watch 状态,可以控制start watch或end watch.
Handler使用的Looper不是System Server Main thread Looper,所以不会卡System Server Main Thread.

3)调用TvInputManagerService  onStart函数
 @Override
    public void onStart() {
        publishBinderService(Context.TV_INPUT_SERVICE, new BinderService());
    }
将ITvInputManager service注册到ServiceManager,在BinderService类中实现ITvInputManager的aidl接口,这个实现代码很长,也是TvInputManagerService主要业务,java api层的接口实现就是在BinderService。

4)调用TvInputManagerService onBootPhase函数
在TvInputManagerService启动时,会call到如下函数:
  @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            registerBroadcastReceivers();
        } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
            synchronized (mLock) {
                buildTvInputListLocked(mCurrentUserId, null);
                buildTvContentRatingSystemListLocked(mCurrentUserId);
            }
        }
        mTvInputHardwareManager.onBootPhase(phase);
    }
对于phase的两种事件解释如下:
  /**
     * After receiving this boot phase, services can safely call into core system services
     * such as the PowerManager or PackageManager.
     */
    public static final int PHASE_SYSTEM_SERVICES_READY = 500;
  /**
     * After receiving this boot phase, services can start/bind to third party apps.
     * Apps will be able to make Binder calls into services at this point.
     */
    public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
看起来是TvInputManagerService在启动时,有两个启动完毕时间点,一个是可以被core service call,另外一种是被third party apps start/bind
在收到PHASE_SYSTEM_SERVICES_READY  event后,会去注册广播接收器:
 private void registerBroadcastReceivers() {
PackageMonitor monitor = new PackageMonitor() {
这里有一个内部类PackageMonitor,有很多的call back接口,以及内部接口:
 private void buildTvInputList(String[] packages) {
                synchronized (mLock) {
                    buildTvInputListLocked(getChangingUserId(), packages);
                    buildTvContentRatingSystemListLocked(getChangingUserId());
                }
            }
call back接口主要为:
public void onPackageUpdateFinished(String packageName, int uid)
public void onPackagesAvailable(String[] packages)
public void onPackagesUnavailable(String[] packages)
public void onSomePackagesChanged()
public boolean onPackageChanged(String packageName, int uid, String[] components)
public void onPackageRemoved(String packageName, int uid)
看起来都是对package事件的处理,那么看下PackageMonitor注册广播类型:
static {
        sPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
        sPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
        sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
        sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
        sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
        sPackageFilt.addDataScheme("package");
        sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED);
        sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED);
        sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
        sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
    }
看起来都是和apps相关的,这里的apps应该是指TvInputService的实现。
在TIF中,每一种通道可以理解为一个Tv Input Device,有一个Tv Input Service去实现相关的业务逻辑。
比如对于Tunel device,有切台,修改音量,创建会话等行为,都需要Tv Input Service去实现。
当Tv Input Service的apps卸载或安装时,会触发这里的广播reciver.
在收到PHASE_THIRD_PARTY_APPS_CAN_START事件时,会去call buildTvInputListLocked函数,
buildTvInputListLocked函数实现如下:
private void buildTvInputListLocked(int userId, String[] updatedPackages) {
       // 获取系统所有的TvInputService,在AndroidManifest.xml中注册TvInputService时需要带关键字TvInputService.SERVICE_INTERFACE
        PackageManager pm = mContext.getPackageManager();
        List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                new Intent(TvInputService.SERVICE_INTERFACE),
                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
                userId);
       ...
      //每一个TvInputService对应一个TvInputInfo,保存TvInput device信息
      List<TvInputInfo> inputList = new ArrayList<>();
      for (ResolveInfo ri : services) {
            ServiceInfo si = ri.serviceInfo;
            //每个TvInputService需要注册BIND_TV_INPUT权限,否则无法启动
            if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) {
                Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission "
                        + android.Manifest.permission.BIND_TV_INPUT);
                continue;
            }
             ComponentName component = new ComponentName(si.packageName, si.name);
           // 注册TvInputService的app要注册TV_INPUT_HARDWARE权限,否则也无法启动
            if (hasHardwarePermission(pm, component)) {
           ...
           serviceState = new ServiceState(component, userId);
            userState.serviceStateMap.put(component, serviceState);
             //绑定TvInputService
             updateServiceConnectionLocked(component, userId);
             ...
            //保存TvInputService对应的TvInputInfo到TvInput List
            inputList.addAll(serviceState.inputList);
            ....
             for (String inputId : inputMap.keySet()) {
            if (!userState.inputMap.containsKey(inputId)) {
               // Tv Input device status变化,通知上层
                notifyInputAddedLocked(userState, inputId);
            } else if (updatedPackages != null) {
                // Notify the package updates
                ComponentName component = inputMap.get(inputId).info.getComponent();
                for (String updatedPackage : updatedPackages) {
                    if (component.getPackageName().equals(updatedPackage)) {
                       // TvInputService所在的apk有更新,更新service的连接状态
                        updateServiceConnectionLocked(component, userId);
                        notifyInputUpdatedLocked(userState, inputId);
                        break;
                    }
                }
            }
        }
      ....
       for (String inputId : userState.inputMap.keySet()) {
            if (!inputMap.containsKey(inputId)) {
                TvInputInfo info = userState.inputMap.get(inputId).info;
                ServiceState serviceState = userState.serviceStateMap.get(info.getComponent());
                if (serviceState != null) {
                    abortPendingCreateSessionRequestsLocked(serviceState, inputId, userId);
                }
                //tv input device有移除,通知上层
                notifyInputRemovedLocked(userState, inputId);
            }
        }
在TIF设计中考虑了Android多用户的情况,不同的用户,可能会安装不同TvInputService组件。因此TvInputService的状态,Tv input device的状态等需要分别去管理。UserState内部类的添加实现了对多用户的支持。

 private static final class UserState {
        // A mapping from the TV input id to its TvInputState.
        private Map<String, TvInputState> inputMap = new HashMap<>();
 
        // A set of all TV input packages.
        private final Set<String> packageSet = new HashSet<>();
 
        // A list of all TV content rating systems defined.
        private final List<TvContentRatingSystemInfo>
                contentRatingSystemList = new ArrayList<>();
 
        // A mapping from the token of a client to its state.
        private final Map<IBinder, ClientState> clientStateMap = new HashMap<>();
 
        // A mapping from the name of a TV input service to its state.
        private final Map<ComponentName, ServiceState> serviceStateMap = new HashMap<>();
 
        // A mapping from the token of a TV input session to its state.
        private final Map<IBinder, SessionState> sessionStateMap = new HashMap<>();
 
        // A set of callbacks.
        private final Set<ITvInputManagerCallback> callbackSet = new HashSet<>();
 
        // The token of a "main" TV input session.
        private IBinder mainSessionToken = null;
 
        // Persistent data store for all internal settings maintained by the TV input manager
        // service.
        private final PersistentDataStore persistentDataStore;
 
        private UserState(Context context, int userId) {
            persistentDataStore = new PersistentDataStore(context, userId);
        }
    }
ServiceState是对TvInputService状态的记录,TvInputState是对TvInputDevice状态的记录,packageset是对所有TvInputService组件的记录。
   private final class ServiceState {
        private final List<IBinder> sessionTokens = new ArrayList<>();
        private final ServiceConnection connection;
        private final ComponentName component;
        private final boolean isHardware;
        private final List<TvInputInfo> inputList = new ArrayList<>();
 
        private ITvInputService service;
        private ServiceCallback callback;
        private boolean bound;
        private boolean reconnecting;
 
        private ServiceState(ComponentName component, int userId) {
            this.component = component;
            this.connection = new InputServiceConnection(component, userId);
            this.isHardware = hasHardwarePermission(mContext.getPackageManager(), component);
        }
    }
 
    private static final class TvInputState {
        // A TvInputInfo object which represents the TV input.
        private TvInputInfo info;
 
        // The state of TV input. Connected by default.
        private int state = INPUT_STATE_CONNECTED;
 
        @Override
        public String toString() {
            return "info: " + info + "; state: " + state;
        }
    }
2 TvInputService启动
启动TvInputService的方法是通过bind方式:
private void updateServiceConnectionLocked(ComponentName component, int userId) {
...
 Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component);
            serviceState.bound = mContext.bindServiceAsUser(
                    i, serviceState.connection,
                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                    new UserHandle(userId));
bind后,可以拿到TvInputService实例。
private final class InputServiceConnection implements ServiceConnection {
...
 @Override
        public void onServiceConnected(ComponentName component, IBinder service) {
            if (DEBUG) {
                Slog.d(TAG, "onServiceConnected(component=" + component + ")");
            }
            synchronized (mLock) {
                UserState userState = getOrCreateUserStateLocked(mUserId);
                ServiceState serviceState = userState.serviceStateMap.get(mComponent);
                serviceState.service = ITvInputService.Stub.asInterface(service);
在TvInputManagerService中会监控设备插拔事件,并将插拔事件给到TvInputService,TvInputService可以进行对应的逻辑处理。

    private final class HardwareListener implements TvInputHardwareManager.Listener {
        @Override
        public void onStateChanged(String inputId, int state) {
            synchronized (mLock) {
                setStateLocked(inputId, state, mCurrentUserId);
            }
        }
 
        @Override
        public void onHardwareDeviceAdded(TvInputHardwareInfo info) {
            synchronized (mLock) {
                UserState userState = getOrCreateUserStateLocked(mCurrentUserId);
                // Broadcast the event to all hardware inputs.
                for (ServiceState serviceState : userState.serviceStateMap.values()) {
                    if (!serviceState.isHardware || serviceState.service == null) continue;
                    try {
                        serviceState.service.notifyHardwareAdded(info);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "error in notifyHardwareAdded", e);
                    }
                }
            }
        }
 
        @Override
        public void onHardwareDeviceRemoved(TvInputHardwareInfo info) {
            synchronized (mLock) {
                UserState userState = getOrCreateUserStateLocked(mCurrentUserId);
                // Broadcast the event to all hardware inputs.
                for (ServiceState serviceState : userState.serviceStateMap.values()) {
                    if (!serviceState.isHardware || serviceState.service == null) continue;
                    try {
                        serviceState.service.notifyHardwareRemoved(info);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "error in notifyHardwareRemoved", e);
                    }
                }
            }
        }
 
        @Override
        public void onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) {
            synchronized (mLock) {
                UserState userState = getOrCreateUserStateLocked(mCurrentUserId);
                // Broadcast the event to all hardware inputs.
                for (ServiceState serviceState : userState.serviceStateMap.values()) {
                    if (!serviceState.isHardware || serviceState.service == null) continue;
                    try {
                        serviceState.service.notifyHdmiDeviceAdded(deviceInfo);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "error in notifyHdmiDeviceAdded", e);
                    }
                }
            }
        }
 
        @Override
        public void onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) {
            synchronized (mLock) {
                UserState userState = getOrCreateUserStateLocked(mCurrentUserId);
                // Broadcast the event to all hardware inputs.
                for (ServiceState serviceState : userState.serviceStateMap.values()) {
                    if (!serviceState.isHardware || serviceState.service == null) continue;
                    try {
                        serviceState.service.notifyHdmiDeviceRemoved(deviceInfo);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e);
                    }
                }
            }
        }
 
        @Override
        public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo deviceInfo) {
            synchronized (mLock) {
                Integer state;
                switch (deviceInfo.getDevicePowerStatus()) {
                    case HdmiControlManager.POWER_STATUS_ON:
                        state = INPUT_STATE_CONNECTED;
                        break;
                    case HdmiControlManager.POWER_STATUS_STANDBY:
                    case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON:
                    case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY:
                        state = INPUT_STATE_CONNECTED_STANDBY;
                        break;
                    case HdmiControlManager.POWER_STATUS_UNKNOWN:
                    default:
                        state = null;
                        break;
                }
                if (state != null) {
                    setStateLocked(inputId, state, mCurrentUserId);
                }
            }
        }
    }
TvInputHardwareManager是辅助TvInputManagerService管理的类。
3 TvInputHardwareManager介绍
在TvInputManagerSerivce的构造函数中会实例化TvInputHardwareManager:
mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener());
参数HardwareListener即是TvInputManagerService监控Hardware的监听器。
 public TvInputHardwareManager(Context context, Listener listener) {
        mContext = context;
        mListener = listener;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mHal.init();
    }
TvInputHardwareManager的构造函数很简单,实例化AudioManager以及HAL init,变量mHal是TvInputHal。
TvInputHal的类继承关系:
final class TvInputHal implements Handler.Callback {
主要功能是处理队列消息。
  public void init() {
        synchronized (mLock) {
            mPtr = nativeOpen(mHandler.getLooper().getQueue());
        }
    }
初始化函数是打开一个Message Queue。
在TvInputManagerService中启动时会call到onBootPhase函数:
public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            IHdmiControlService hdmiControlService = IHdmiControlService.Stub.asInterface(
                    ServiceManager.getService(Context.HDMI_CONTROL_SERVICE));
            if (hdmiControlService != null) {
                try {
                    hdmiControlService.addHotplugEventListener(mHdmiHotplugEventListener);
                    hdmiControlService.addDeviceEventListener(mHdmiDeviceEventListener);
                    hdmiControlService.addSystemAudioModeChangeListener(
                            mHdmiSystemAudioModeChangeListener);
                    mHdmiDeviceList.addAll(hdmiControlService.getInputDevices());
                } catch (RemoteException e) {
                    Slog.w(TAG, "Error registering listeners to HdmiControlService:", e);
                }
            } else {
                Slog.w(TAG, "HdmiControlService is not available");
            }
            final IntentFilter filter = new IntentFilter();
            filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
            filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
            mContext.registerReceiver(mVolumeReceiver, filter);
            updateVolume();
        }
    }
主要是对HDMI Control service实例化以及初始化,并注册音量变化广播。
TvInputHardwareManager类的实现:
class TvInputHardwareManager implements TvInputHal.Callback
TvInputHal主要是对Message队列消息的处理,Callback函数定义如下:
    public interface Callback {
        void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs);
        void onDeviceUnavailable(int deviceId);
        void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs);
        void onFirstFrameCaptured(int deviceId, int streamId);
    }
即TvInputHardwareManager对device状态的监听,是由TvInputHal通知出来。
TvInputHal.java
    // Called from native
    private void deviceAvailableFromNative(TvInputHardwareInfo info) {
        if (DEBUG) {
            Slog.d(TAG, "deviceAvailableFromNative: info = " + info);
        }
        mHandler.obtainMessage(EVENT_DEVICE_AVAILABLE, info).sendToTarget();
    }
 
    private void deviceUnavailableFromNative(int deviceId) {
        mHandler.obtainMessage(EVENT_DEVICE_UNAVAILABLE, deviceId, 0).sendToTarget();
    }
 
    private void streamConfigsChangedFromNative(int deviceId) {
        mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget();
    }
 
    private void firstFrameCapturedFromNative(int deviceId, int streamId) {
        mHandler.sendMessage(
                mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, streamId));
    }
JNI层call到TvInputHal java层接口,将Event给到TvInputHal层,TvInputHal发送Handler消息,在HandlerMessage函数处理handler消息:
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_DEVICE_AVAILABLE: {
                TvStreamConfig[] configs;
                TvInputHardwareInfo info = (TvInputHardwareInfo)msg.obj;
                synchronized (mLock) {
                    retrieveStreamConfigsLocked(info.getDeviceId());
                    if (DEBUG) {
                        Slog.d(TAG, "EVENT_DEVICE_AVAILABLE: info = " + info);
                    }
                    configs = mStreamConfigs.get(info.getDeviceId());
                }
                mCallback.onDeviceAvailable(info, configs);
                break;
            }
 
            case EVENT_DEVICE_UNAVAILABLE: {
                int deviceId = msg.arg1;
                if (DEBUG) {
                    Slog.d(TAG, "EVENT_DEVICE_UNAVAILABLE: deviceId = " + deviceId);
                }
                mCallback.onDeviceUnavailable(deviceId);
                break;
            }
 
            case EVENT_STREAM_CONFIGURATION_CHANGED: {
                TvStreamConfig[] configs;
                int deviceId = msg.arg1;
                synchronized (mLock) {
                    if (DEBUG) {
                        Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId);
                    }
                    retrieveStreamConfigsLocked(deviceId);
                    configs = mStreamConfigs.get(deviceId);
                }
                mCallback.onStreamConfigurationChanged(deviceId, configs);
                break;
            }
 
            case EVENT_FIRST_FRAME_CAPTURED: {
                int deviceId = msg.arg1;
                int streamId = msg.arg2;
                mCallback.onFirstFrameCaptured(deviceId, streamId);
                break;
            }
 
            default:
                Slog.e(TAG, "Unknown event: " + msg);
                return false;
        }
 
        return true;
    }
处理Handler消息即通过callback将Message给到TvInputHardwareManager。

Tv Input Device state变化的流程可以汇总如下:
HAL->JNI->TvInputHal->TvInputHardwareManager->TvInputManagerService->TvInputService

通过这篇文章,学习了TvInputManagerService启动TvInputService的过程,以及TvInputManagerService,TvInputHardwareManager以及TvinputHal传递TvInputDevice的流程。

--------------------- 
作者:zhudaozhuan 
来源:CSDN 
原文:https://blog.csdn.net/zhudaozhuan/article/details/50849542 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值