Loading media/java/android/media/tv/ITvInputManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.media.tv.ITvInputClient; import android.media.tv.ITvInputHardware; import android.media.tv.ITvInputHardwareCallback; import android.media.tv.ITvInputManagerCallback; import android.media.tv.TvChannelInfo; import android.media.tv.TvContentRatingSystemInfo; import android.media.tv.TvInputHardwareInfo; import android.media.tv.TvInputInfo; Loading Loading @@ -88,6 +89,8 @@ interface ITvInputManager { void timeShiftSetPlaybackParams(in IBinder sessionToken, in PlaybackParams params, int userId); void timeShiftEnablePositionTracking(in IBinder sessionToken, boolean enable, int userId); List<TvChannelInfo> getTvCurrentChannelInfos(int userId); // For the recording session void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId); void stopRecording(in IBinder sessionToken, int userId); Loading media/java/android/media/tv/TvChannelInfo.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * Copyright 2020 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.media.tv; parcelable TvChannelInfo; media/java/android/media/tv/TvChannelInfo.java 0 → 100644 +148 −0 Original line number Diff line number Diff line /* * Copyright 2020 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.media.tv; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * @hide */ public final class TvChannelInfo implements Parcelable { static final String TAG = "TvChannelInfo"; public static final int APP_TAG_SELF = 0; public static final int APP_TYPE_SELF = 1; public static final int APP_TYPE_SYSTEM = 2; public static final int APP_TYPE_NON_SYSTEM = 3; /** @hide */ @IntDef(prefix = "APP_TYPE_", value = {APP_TYPE_SELF, APP_TYPE_SYSTEM, APP_TYPE_NON_SYSTEM}) @Retention(RetentionPolicy.SOURCE) public @interface AppType {} public static final @NonNull Parcelable.Creator<TvChannelInfo> CREATOR = new Parcelable.Creator<TvChannelInfo>() { @Override public TvChannelInfo createFromParcel(Parcel source) { try { return new TvChannelInfo(source); } catch (Exception e) { Log.e(TAG, "Exception creating TvChannelInfo from parcel", e); return null; } } @Override public TvChannelInfo[] newArray(int size) { return new TvChannelInfo[size]; } }; private final String mInputId; @Nullable private final Uri mChannelUri; private final boolean mIsRecordingSession; private final boolean mIsForeground; @AppType private final int mAppType; private final int mAppTag; public TvChannelInfo( String inputId, @Nullable Uri channelUri, boolean isRecordingSession, boolean isForeground, @AppType int appType, int appTag) { mInputId = inputId; mChannelUri = channelUri; mIsRecordingSession = isRecordingSession; mIsForeground = isForeground; mAppType = appType; mAppTag = appTag; } private TvChannelInfo(Parcel source) { mInputId = source.readString(); String uriString = source.readString(); mChannelUri = uriString == null ? null : Uri.parse(uriString); mIsRecordingSession = (source.readInt() == 1); mIsForeground = (source.readInt() == 1); mAppType = source.readInt(); mAppTag = source.readInt(); } public String getInputId() { return mInputId; } public Uri getChannelUri() { return mChannelUri; } public boolean isRecordingSession() { return mIsRecordingSession; } public boolean isForeground() { return mIsForeground; } /** * Gets app tag. * <p>App tag is used to differentiate one app from another. * {@link #APP_TAG_SELF} is for current app. */ public int getAppTag() { return mAppTag; } @AppType public int getAppType() { return mAppType; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mInputId); String uriString = mChannelUri == null ? null : mChannelUri.toString(); dest.writeString(uriString); dest.writeInt(mIsRecordingSession ? 1 : 0); dest.writeInt(mIsForeground ? 1 : 0); dest.writeInt(mAppType); dest.writeInt(mAppTag); } @Override public String toString() { return "inputID=" + mInputId + ";channelUri=" + mChannelUri + ";isRecording=" + mIsRecordingSession + ";isForeground=" + mIsForeground + ";appType=" + mAppType + ";appTag=" + mAppTag; } } media/java/android/media/tv/TvInputManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -1952,6 +1952,19 @@ public final class TvInputManager { } } /** * @hide */ public List<TvChannelInfo> getTvCurrentChannelInfos() { // TODO: handle retuned() cases and add a method to TvInputCallback // TODO: unhide try { return mService.getTvCurrentChannelInfos(mUserId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * The Session provides the per-session functionality of TV inputs. * @hide Loading services/core/java/com/android/server/tv/TvInputManagerService.java +103 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; Loading @@ -33,6 +35,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; Loading @@ -51,6 +54,7 @@ import android.media.tv.ITvInputService; import android.media.tv.ITvInputServiceCallback; import android.media.tv.ITvInputSession; import android.media.tv.ITvInputSessionCallback; import android.media.tv.TvChannelInfo; import android.media.tv.TvContentRating; import android.media.tv.TvContentRatingSystemInfo; import android.media.tv.TvContract; Loading Loading @@ -78,6 +82,7 @@ import android.util.SparseArray; import android.view.InputChannel; import android.view.Surface; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.os.SomeArgs; import com.android.internal.util.DumpUtils; Loading Loading @@ -108,6 +113,9 @@ public final class TvInputManagerService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "TvInputManagerService"; private static final String DVB_DIRECTORY = "/dev/dvb"; private static final int APP_TAG_SELF = TvChannelInfo.APP_TAG_SELF; private static final String PERMISSION_ACCESS_WATCHED_PROGRAMS = "com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS"; // There are two different formats of DVB frontend devices. One is /dev/dvb%d.frontend%d, // another one is /dev/dvb/adapter%d/frontend%d. Followings are the patterns for selecting the Loading Loading @@ -136,6 +144,8 @@ public final class TvInputManagerService extends SystemService { private final WatchLogHandler mWatchLogHandler; private final ActivityManager mActivityManager; public TvInputManagerService(Context context) { super(context); Loading @@ -144,6 +154,9 @@ public final class TvInputManagerService extends SystemService { IoThread.get().getLooper()); mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); mActivityManager = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE); synchronized (mLock) { getOrCreateUserStateLocked(mCurrentUserId); } Loading Loading @@ -694,6 +707,8 @@ public final class TvInputManagerService extends SystemService { sessionState.session.asBinder().unlinkToDeath(sessionState, 0); sessionState.session.release(); } sessionState.isCurrent = false; sessionState.currentChannel = null; } catch (RemoteException | SessionNotFoundException e) { Slog.e(TAG, "error in releaseSession", e); } finally { Loading Loading @@ -1394,13 +1409,17 @@ public final class TvInputManagerService extends SystemService { try { getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( channelUri, params); UserState userState = getOrCreateUserStateLocked(resolvedUserId); SessionState sessionState = userState.sessionStateMap.get(sessionToken); if (sessionState != null) { sessionState.isCurrent = true; sessionState.currentChannel = channelUri; } if (TvContract.isChannelUriForPassthroughInput(channelUri)) { // Do not log the watch history for passthrough inputs. return; } UserState userState = getOrCreateUserStateLocked(resolvedUserId); SessionState sessionState = userState.sessionStateMap.get(sessionToken); if (sessionState.isRecordingSession) { return; } Loading Loading @@ -2049,6 +2068,80 @@ public final class TvInputManagerService extends SystemService { return clientPid; } @Override public List<TvChannelInfo> getTvCurrentChannelInfos(@UserIdInt int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Binder.getCallingUid(), userId, "getTvCurrentChannelInfos"); final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { UserState userState = getOrCreateUserStateLocked(resolvedUserId); List<TvChannelInfo> channelInfos = new ArrayList<>(); boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission(); for (SessionState state : userState.sessionStateMap.values()) { if (state.isCurrent) { Integer appTag; int appType; if (state.callingUid == Binder.getCallingUid()) { appTag = APP_TAG_SELF; appType = TvChannelInfo.APP_TYPE_SELF; } else { appTag = userState.mAppTagMap.get(state.callingUid); if (appTag == null) { appTag = userState.mNextAppTag++; userState.mAppTagMap.put(state.callingUid, appTag); } appType = isSystemApp(state.componentName.getPackageName()) ? TvChannelInfo.APP_TYPE_SYSTEM : TvChannelInfo.APP_TYPE_NON_SYSTEM; } channelInfos.add(new TvChannelInfo( state.inputId, watchedProgramsAccess ? state.currentChannel : null, state.isRecordingSession, isForeground(state.callingPid), appType, appTag)); } } return channelInfos; } } finally { Binder.restoreCallingIdentity(identity); } } protected boolean isForeground(int pid) { if (mActivityManager == null) { return false; } List<RunningAppProcessInfo> appProcesses = mActivityManager.getRunningAppProcesses(); if (appProcesses == null) { return false; } for (RunningAppProcessInfo appProcess : appProcesses) { if (appProcess.pid == pid && appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } return false; } private boolean hasAccessWatchedProgramsPermission() { return mContext.checkCallingPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS) == PackageManager.PERMISSION_GRANTED; } private boolean isSystemApp(String pkg) { try { return (mContext.getPackageManager().getApplicationInfo(pkg, 0).flags & ApplicationInfo.FLAG_SYSTEM) != 0; } catch (NameNotFoundException e) { return false; } } /** * Add a hardware device in the TvInputHardwareManager for CTS testing * purpose. Loading Loading @@ -2250,6 +2343,11 @@ public final class TvInputManagerService extends SystemService { // service. private final PersistentDataStore persistentDataStore; @GuardedBy("mLock") private final Map<Integer, Integer> mAppTagMap = new HashMap<>(); @GuardedBy("mLock") private int mNextAppTag = 1; private UserState(Context context, int userId) { persistentDataStore = new PersistentDataStore(context, userId); } Loading Loading @@ -2336,6 +2434,9 @@ public final class TvInputManagerService extends SystemService { // Not null if this session represents an external device connected to a hardware TV input. private IBinder hardwareSessionToken; private boolean isCurrent = false; private Uri currentChannel = null; private SessionState(IBinder sessionToken, String inputId, ComponentName componentName, boolean isRecordingSession, ITvInputClient client, int seq, int callingUid, int callingPid, int userId, String sessionId) { Loading Loading
media/java/android/media/tv/ITvInputManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.media.tv.ITvInputClient; import android.media.tv.ITvInputHardware; import android.media.tv.ITvInputHardwareCallback; import android.media.tv.ITvInputManagerCallback; import android.media.tv.TvChannelInfo; import android.media.tv.TvContentRatingSystemInfo; import android.media.tv.TvInputHardwareInfo; import android.media.tv.TvInputInfo; Loading Loading @@ -88,6 +89,8 @@ interface ITvInputManager { void timeShiftSetPlaybackParams(in IBinder sessionToken, in PlaybackParams params, int userId); void timeShiftEnablePositionTracking(in IBinder sessionToken, boolean enable, int userId); List<TvChannelInfo> getTvCurrentChannelInfos(int userId); // For the recording session void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId); void stopRecording(in IBinder sessionToken, int userId); Loading
media/java/android/media/tv/TvChannelInfo.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * Copyright 2020 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.media.tv; parcelable TvChannelInfo;
media/java/android/media/tv/TvChannelInfo.java 0 → 100644 +148 −0 Original line number Diff line number Diff line /* * Copyright 2020 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.media.tv; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * @hide */ public final class TvChannelInfo implements Parcelable { static final String TAG = "TvChannelInfo"; public static final int APP_TAG_SELF = 0; public static final int APP_TYPE_SELF = 1; public static final int APP_TYPE_SYSTEM = 2; public static final int APP_TYPE_NON_SYSTEM = 3; /** @hide */ @IntDef(prefix = "APP_TYPE_", value = {APP_TYPE_SELF, APP_TYPE_SYSTEM, APP_TYPE_NON_SYSTEM}) @Retention(RetentionPolicy.SOURCE) public @interface AppType {} public static final @NonNull Parcelable.Creator<TvChannelInfo> CREATOR = new Parcelable.Creator<TvChannelInfo>() { @Override public TvChannelInfo createFromParcel(Parcel source) { try { return new TvChannelInfo(source); } catch (Exception e) { Log.e(TAG, "Exception creating TvChannelInfo from parcel", e); return null; } } @Override public TvChannelInfo[] newArray(int size) { return new TvChannelInfo[size]; } }; private final String mInputId; @Nullable private final Uri mChannelUri; private final boolean mIsRecordingSession; private final boolean mIsForeground; @AppType private final int mAppType; private final int mAppTag; public TvChannelInfo( String inputId, @Nullable Uri channelUri, boolean isRecordingSession, boolean isForeground, @AppType int appType, int appTag) { mInputId = inputId; mChannelUri = channelUri; mIsRecordingSession = isRecordingSession; mIsForeground = isForeground; mAppType = appType; mAppTag = appTag; } private TvChannelInfo(Parcel source) { mInputId = source.readString(); String uriString = source.readString(); mChannelUri = uriString == null ? null : Uri.parse(uriString); mIsRecordingSession = (source.readInt() == 1); mIsForeground = (source.readInt() == 1); mAppType = source.readInt(); mAppTag = source.readInt(); } public String getInputId() { return mInputId; } public Uri getChannelUri() { return mChannelUri; } public boolean isRecordingSession() { return mIsRecordingSession; } public boolean isForeground() { return mIsForeground; } /** * Gets app tag. * <p>App tag is used to differentiate one app from another. * {@link #APP_TAG_SELF} is for current app. */ public int getAppTag() { return mAppTag; } @AppType public int getAppType() { return mAppType; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mInputId); String uriString = mChannelUri == null ? null : mChannelUri.toString(); dest.writeString(uriString); dest.writeInt(mIsRecordingSession ? 1 : 0); dest.writeInt(mIsForeground ? 1 : 0); dest.writeInt(mAppType); dest.writeInt(mAppTag); } @Override public String toString() { return "inputID=" + mInputId + ";channelUri=" + mChannelUri + ";isRecording=" + mIsRecordingSession + ";isForeground=" + mIsForeground + ";appType=" + mAppType + ";appTag=" + mAppTag; } }
media/java/android/media/tv/TvInputManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -1952,6 +1952,19 @@ public final class TvInputManager { } } /** * @hide */ public List<TvChannelInfo> getTvCurrentChannelInfos() { // TODO: handle retuned() cases and add a method to TvInputCallback // TODO: unhide try { return mService.getTvCurrentChannelInfos(mUserId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * The Session provides the per-session functionality of TV inputs. * @hide Loading
services/core/java/com/android/server/tv/TvInputManagerService.java +103 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; Loading @@ -33,6 +35,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; Loading @@ -51,6 +54,7 @@ import android.media.tv.ITvInputService; import android.media.tv.ITvInputServiceCallback; import android.media.tv.ITvInputSession; import android.media.tv.ITvInputSessionCallback; import android.media.tv.TvChannelInfo; import android.media.tv.TvContentRating; import android.media.tv.TvContentRatingSystemInfo; import android.media.tv.TvContract; Loading Loading @@ -78,6 +82,7 @@ import android.util.SparseArray; import android.view.InputChannel; import android.view.Surface; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.os.SomeArgs; import com.android.internal.util.DumpUtils; Loading Loading @@ -108,6 +113,9 @@ public final class TvInputManagerService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "TvInputManagerService"; private static final String DVB_DIRECTORY = "/dev/dvb"; private static final int APP_TAG_SELF = TvChannelInfo.APP_TAG_SELF; private static final String PERMISSION_ACCESS_WATCHED_PROGRAMS = "com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS"; // There are two different formats of DVB frontend devices. One is /dev/dvb%d.frontend%d, // another one is /dev/dvb/adapter%d/frontend%d. Followings are the patterns for selecting the Loading Loading @@ -136,6 +144,8 @@ public final class TvInputManagerService extends SystemService { private final WatchLogHandler mWatchLogHandler; private final ActivityManager mActivityManager; public TvInputManagerService(Context context) { super(context); Loading @@ -144,6 +154,9 @@ public final class TvInputManagerService extends SystemService { IoThread.get().getLooper()); mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); mActivityManager = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE); synchronized (mLock) { getOrCreateUserStateLocked(mCurrentUserId); } Loading Loading @@ -694,6 +707,8 @@ public final class TvInputManagerService extends SystemService { sessionState.session.asBinder().unlinkToDeath(sessionState, 0); sessionState.session.release(); } sessionState.isCurrent = false; sessionState.currentChannel = null; } catch (RemoteException | SessionNotFoundException e) { Slog.e(TAG, "error in releaseSession", e); } finally { Loading Loading @@ -1394,13 +1409,17 @@ public final class TvInputManagerService extends SystemService { try { getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( channelUri, params); UserState userState = getOrCreateUserStateLocked(resolvedUserId); SessionState sessionState = userState.sessionStateMap.get(sessionToken); if (sessionState != null) { sessionState.isCurrent = true; sessionState.currentChannel = channelUri; } if (TvContract.isChannelUriForPassthroughInput(channelUri)) { // Do not log the watch history for passthrough inputs. return; } UserState userState = getOrCreateUserStateLocked(resolvedUserId); SessionState sessionState = userState.sessionStateMap.get(sessionToken); if (sessionState.isRecordingSession) { return; } Loading Loading @@ -2049,6 +2068,80 @@ public final class TvInputManagerService extends SystemService { return clientPid; } @Override public List<TvChannelInfo> getTvCurrentChannelInfos(@UserIdInt int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Binder.getCallingUid(), userId, "getTvCurrentChannelInfos"); final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { UserState userState = getOrCreateUserStateLocked(resolvedUserId); List<TvChannelInfo> channelInfos = new ArrayList<>(); boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission(); for (SessionState state : userState.sessionStateMap.values()) { if (state.isCurrent) { Integer appTag; int appType; if (state.callingUid == Binder.getCallingUid()) { appTag = APP_TAG_SELF; appType = TvChannelInfo.APP_TYPE_SELF; } else { appTag = userState.mAppTagMap.get(state.callingUid); if (appTag == null) { appTag = userState.mNextAppTag++; userState.mAppTagMap.put(state.callingUid, appTag); } appType = isSystemApp(state.componentName.getPackageName()) ? TvChannelInfo.APP_TYPE_SYSTEM : TvChannelInfo.APP_TYPE_NON_SYSTEM; } channelInfos.add(new TvChannelInfo( state.inputId, watchedProgramsAccess ? state.currentChannel : null, state.isRecordingSession, isForeground(state.callingPid), appType, appTag)); } } return channelInfos; } } finally { Binder.restoreCallingIdentity(identity); } } protected boolean isForeground(int pid) { if (mActivityManager == null) { return false; } List<RunningAppProcessInfo> appProcesses = mActivityManager.getRunningAppProcesses(); if (appProcesses == null) { return false; } for (RunningAppProcessInfo appProcess : appProcesses) { if (appProcess.pid == pid && appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } return false; } private boolean hasAccessWatchedProgramsPermission() { return mContext.checkCallingPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS) == PackageManager.PERMISSION_GRANTED; } private boolean isSystemApp(String pkg) { try { return (mContext.getPackageManager().getApplicationInfo(pkg, 0).flags & ApplicationInfo.FLAG_SYSTEM) != 0; } catch (NameNotFoundException e) { return false; } } /** * Add a hardware device in the TvInputHardwareManager for CTS testing * purpose. Loading Loading @@ -2250,6 +2343,11 @@ public final class TvInputManagerService extends SystemService { // service. private final PersistentDataStore persistentDataStore; @GuardedBy("mLock") private final Map<Integer, Integer> mAppTagMap = new HashMap<>(); @GuardedBy("mLock") private int mNextAppTag = 1; private UserState(Context context, int userId) { persistentDataStore = new PersistentDataStore(context, userId); } Loading Loading @@ -2336,6 +2434,9 @@ public final class TvInputManagerService extends SystemService { // Not null if this session represents an external device connected to a hardware TV input. private IBinder hardwareSessionToken; private boolean isCurrent = false; private Uri currentChannel = null; private SessionState(IBinder sessionToken, String inputId, ComponentName componentName, boolean isRecordingSession, ITvInputClient client, int seq, int callingUid, int callingPid, int userId, String sessionId) { Loading