TvInputManagerService.java revision 15c56aac985bc8d75f38fb4ecb92dda12d2ca06c
13957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/* 23957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Copyright (C) 2014 The Android Open Source Project 33957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 43957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Licensed under the Apache License, Version 2.0 (the "License"); 53957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * you may not use this file except in compliance with the License. 63957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * You may obtain a copy of the License at 73957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 83957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * http://www.apache.org/licenses/LICENSE-2.0 93957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Unless required by applicable law or agreed to in writing, software 113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * distributed under the License is distributed on an "AS IS" BASIS, 123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * See the License for the specific language governing permissions and 143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * limitations under the License. 153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo */ 163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopackage com.android.server.tv; 183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; 20e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; 21969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED; 22969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.app.ActivityManager; 243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.BroadcastReceiver; 253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ComponentName; 265c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderOperation; 275c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderResult; 2831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentResolver; 2931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentUris; 3031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentValues; 313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Context; 323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Intent; 333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.IntentFilter; 345c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.OperationApplicationException; 353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ServiceConnection; 363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.PackageManager; 373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ResolveInfo; 383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ServiceInfo; 399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.graphics.Rect; 40e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kimimport android.hardware.hdmi.HdmiControlManager; 4161f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jangimport android.hardware.hdmi.HdmiDeviceInfo; 42d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputClient; 43d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardware; 44d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardwareCallback; 45d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputManager; 46969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.media.tv.ITvInputManagerCallback; 47d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputService; 48d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputServiceCallback; 49d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSession; 50d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSessionCallback; 51783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seoimport android.media.tv.TvContentRating; 52d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvContract; 53d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputHardwareInfo; 54d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputInfo; 55d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputService; 56c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heoimport android.media.tv.TvStreamConfig; 571f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport android.media.tv.TvTrackInfo; 583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.net.Uri; 593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Binder; 60832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 6131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Handler; 623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.IBinder; 6331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Looper; 6431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Message; 653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Process; 663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.RemoteException; 673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.UserHandle; 689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Slog; 693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.util.SparseArray; 706a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputChannel; 713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.view.Surface; 723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.internal.content.PackageMonitor; 7431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.internal.os.SomeArgs; 75e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport com.android.internal.util.IndentingPrintWriter; 7631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.server.IoThread; 773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.server.SystemService; 783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 79e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport org.xmlpull.v1.XmlPullParserException; 80e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee 81e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.FileDescriptor; 82e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport java.io.IOException; 83e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.PrintWriter; 843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.ArrayList; 853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.HashMap; 865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.HashSet; 87187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport java.util.Iterator; 883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.List; 893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.Map; 905c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.Set; 913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/** This class provides a system service that manages television inputs. */ 933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopublic final class TvInputManagerService extends SystemService { 943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // STOPSHIP: Turn debugging off. 953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final boolean DEBUG = true; 963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final String TAG = "TvInputManagerService"; 973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Context mContext; 99c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareManager mTvInputHardwareManager; 1003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final ContentResolver mContentResolver; 10231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A global lock. 1043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Object mLock = new Object(); 1053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // ID of the current user. 1073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int mCurrentUserId = UserHandle.USER_OWNER; 1083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A map from user id to UserState. 1103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 1113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1127eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private final WatchLogHandler mWatchLogHandler; 11331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 1197eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mWatchLogHandler = new WatchLogHandler(IoThread.get().getLooper()); 12031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 121187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); 12231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 124783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo mUserStates.put(mCurrentUserId, new UserState(mContext, mCurrentUserId)); 1253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onStart() { 1303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo publishBinderService(Context.TV_INPUT_SERVICE, new BinderService()); 1313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1330ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee @Override 1340ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee public void onBootPhase(int phase) { 1350ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1360ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee registerBroadcastReceivers(); 137187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 1380ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee synchronized (mLock) { 1390ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee buildTvInputListLocked(mCurrentUserId); 1400ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1410ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 142969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.onBootPhase(phase); 1430ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1440ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee 1453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void registerBroadcastReceivers() { 1463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageMonitor monitor = new PackageMonitor() { 1473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSomePackagesChanged() { 1493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(mCurrentUserId); 1513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1535c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo @Override 1555c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo public void onPackageRemoved(String packageName, int uid) { 1565c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo synchronized (mLock) { 1575c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo UserState userState = getUserStateLocked(mCurrentUserId); 158969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (!userState.packageSet.contains(packageName)) { 1595c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo // Not a TV input package. 1605c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo return; 1615c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1625c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1635c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1645c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ArrayList<ContentProviderOperation> operations = 1655c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo new ArrayList<ContentProviderOperation>(); 1665c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1675c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; 1685c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String[] selectionArgs = { packageName }; 1695c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1705c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI) 1715c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI) 1735c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1745c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation 1755c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .newDelete(TvContract.WatchedPrograms.CONTENT_URI) 1765c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ContentProviderResult[] results = null; 1795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo try { 1805c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations); 1815c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } catch (RemoteException | OperationApplicationException e) { 1825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.e(TAG, "error in applyBatch" + e); 1835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo if (DEBUG) { 1865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid 1875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo + ")"); 1885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "results=" + results); 1895c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1905c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 1923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo monitor.register(mContext, null, UserHandle.ALL, true); 1933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo IntentFilter intentFilter = new IntentFilter(); 1953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 1963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext.registerReceiverAsUser(new BroadcastReceiver() { 1983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onReceive(Context context, Intent intent) { 2003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String action = intent.getAction(); 2013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (Intent.ACTION_USER_SWITCHED.equals(action)) { 2023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 2043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }, UserHandle.ALL, intentFilter, null, null); 2083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2109e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private static boolean hasHardwarePermission(PackageManager pm, ComponentName component) { 211187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, 2129e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee component.getPackageName()) == PackageManager.PERMISSION_GRANTED; 213187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 214187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void buildTvInputListLocked(int userId) { 2163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 217969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.packageSet.clear(); 2183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2199a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (DEBUG) Slog.d(TAG, "buildTvInputList"); 2203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageManager pm = mContext.getPackageManager(); 2213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo List<ResolveInfo> services = pm.queryIntentServices( 222e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee new Intent(TvInputService.SERVICE_INTERFACE), 223e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 2244f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 2253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ResolveInfo ri : services) { 2263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ServiceInfo si = ri.serviceInfo; 2273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { 2289a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission " 2293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + android.Manifest.permission.BIND_TV_INPUT); 2303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo continue; 2313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2329cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo 2339cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo ComponentName component = new ComponentName(si.packageName, si.name); 2349cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (hasHardwarePermission(pm, component)) { 2359cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo ServiceState serviceState = userState.serviceStateMap.get(component); 2369cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (serviceState == null) { 2379cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // We see this hardware TV input service for the first time; we need to 2389cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // prepare the ServiceState object so that we can connect to the service and 2399cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // let it add TvInputInfo objects to mInputList if there's any. 2409cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo serviceState = new ServiceState(component, userId); 2419cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo userState.serviceStateMap.put(component, serviceState); 242187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2439cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo inputList.addAll(serviceState.mInputList); 244187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2459cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } else { 2469cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo try { 2479cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); 2489cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } catch (XmlPullParserException | IOException e) { 2499cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo Slog.e(TAG, "Failed to load TV input " + si.name, e); 2509cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo continue; 251969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2529cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } 253226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 2549cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // Reconnect the service if existing input is updated. 2559cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo updateServiceConnectionLocked(component, userId); 2569cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo userState.packageSet.add(si.packageName); 2579cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } 258187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2599cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 2609cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo for (TvInputInfo info : inputList) { 2619cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (DEBUG) Slog.d(TAG, "add " + info.getId()); 2629cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo TvInputState state = userState.inputMap.get(info.getId()); 2639cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (state == null) { 2649cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo state = new TvInputState(); 265e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 2669cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo state.mInfo = info; 2679cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo inputMap.put(info.getId(), state); 2683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : inputMap.keySet()) { 2718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!userState.inputMap.containsKey(inputId)) { 2728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputAddedLocked(userState, inputId); 2738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : userState.inputMap.keySet()) { 2778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!inputMap.containsKey(inputId)) { 2788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputRemovedLocked(userState, inputId); 2798e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2808e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2818e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2828e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap.clear(); 2838e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap = inputMap; 2845c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 2855c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.clear(); 2865c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(TvContentRating.SYSTEM_CONTENT_RATING_SYSTEM_XML); 2875c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim for (TvInputState state : userState.inputMap.values()) { 2885c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri(); 2895c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim if (ratingSystemXmlUri != null) { 2905c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // TODO: need to check the validation of xml format and the duplication of rating 2915c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // systems. 2925c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(state.mInfo.getRatingSystemXmlUri()); 2935c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2945c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 2983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 2993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 3043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 3053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 308783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState = new UserState(mContext, userId); 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 3113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 3123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 317b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 318b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 319b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 320b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 3213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 3223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 323d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 3243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 325d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 3263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 3283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 3323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 3343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 335d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 3363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 337d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 3383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 3403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 342d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 3433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 3453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 34672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 34772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 3483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 3493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3609e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState getServiceStateLocked(ComponentName component, int userId) { 3613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3629e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 3633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 3649e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee throw new IllegalStateException("Service state not found for " + component + " (userId=" 3657de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3702b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 377d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3812b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3822b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3832b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3842b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3854c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return getSessionLocked(getSessionStateLocked(sessionToken, callingUid, userId)); 3864c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 3874c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 3884c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private ITvInputSession getSessionLocked(SessionState sessionState) { 389d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3914c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee throw new IllegalStateException("Session not yet created for token " 3924c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee + sessionState.mSessionToken); 3933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 3953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 3983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 3993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 4003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 4013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 403187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean shouldMaintainConnection(ServiceState serviceState) { 4049cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo return !serviceState.mSessionTokens.isEmpty() || serviceState.mIsHardware; 405187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // TODO: Find a way to maintain connection only when necessary. 406187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 407187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 4089e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private void updateServiceConnectionLocked(ComponentName component, int userId) { 4093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 4109e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 4113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 4123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting) { 4152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!serviceState.mSessionTokens.isEmpty()) { 4162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // wait until all the sessions are removed. 4172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 4182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 4192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = false; 4202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 421187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean maintainConnection = shouldMaintainConnection(serviceState); 422187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mService == null && maintainConnection && userId == mCurrentUserId) { 4233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is not yet connected but its state indicates that we 4243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // have pending requests. Then, connect the service. 425d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mBound) { 4263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // We have already bound to the service so we don't try to bind again until after we 4273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // unbind later on. 4283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4319e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "bindServiceAsUser(service=" + component + ", userId=" + userId + ")"); 4323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 433d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim 4349e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component); 435226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Binding service may fail if the service is updating. 436226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // In that case, the connection will be revived in buildTvInputListLocked called by 437226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // onSomePackagesChanged. 438e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee serviceState.mBound = mContext.bindServiceAsUser( 439e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); 440187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (serviceState.mService != null && !maintainConnection) { 4413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is already connected but its state indicates that we have 4423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // nothing to do with it. Then, disconnect the service. 4433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4449e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "unbindService(service=" + component + ")"); 4453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 446d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 4479e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee userState.serviceStateMap.remove(component); 4483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 45172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 45272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 45372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 45472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 45572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 45672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 45772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 45872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 45972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 46072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 46172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 46272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4647de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 46572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 46672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 468187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")"); 4693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4706a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4716a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4726a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 476bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) { 4773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 478187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")"); 4793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 481d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 482bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken = harewareSessionToken; 483fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 484fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 485187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 486187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 487fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 4882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 4892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 4902b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 4912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 4922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 49372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 49472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 49572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 49672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 49772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 49872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 49972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 50072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 501187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 502187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), sessionToken, channels[0], 503187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mSeq); 504fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 5056a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 5063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 508832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 509832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 5101f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 511a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 512a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5131f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 514a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 515a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 516a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 517a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 518a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 5201f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 5211f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 5221f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 5231f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 524a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 526a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 527a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 528a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 529a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 530a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 53110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTracksChanged(List<TvTrackInfo> tracks) { 532a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 533a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 53410d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTracksChanged(" + tracks + ")"); 535a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 536a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 537a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 538a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 539a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 54010d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTracksChanged(tracks, sessionState.mSeq); 541a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 54210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTracksChanged"); 543b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 544b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 545b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 546b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 547b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 54810d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTrackSelected(int type, String trackId) { 549d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo synchronized (mLock) { 550d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (DEBUG) { 55110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")"); 552d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 553d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 554d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo return; 555d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 556d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo try { 55710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTrackSelected(type, trackId, sessionState.mSeq); 558d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } catch (RemoteException e) { 55910d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTrackSelected"); 560d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 561d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 562d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 563d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 564d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo @Override 5659b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 5669b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5679b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5689b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 5699b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5709b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5719b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5729b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5739b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5749b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 5759b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5769b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5779b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5789b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5799b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5809b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5819b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 5829b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 5839b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5849b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5859b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 5869b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5879b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5889b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5899b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5909b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5919b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 5929b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5939b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 5949b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5959b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5969b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5979b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5989b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 599bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed() { 600bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo synchronized (mLock) { 601bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 602bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.d(TAG, "onContentAllowed()"); 603bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 604bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 605bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo return; 606bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 607bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo try { 608bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo sessionState.mClient.onContentAllowed(sessionState.mSeq); 609bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } catch (RemoteException e) { 610bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.e(TAG, "error in onContentAllowed"); 611bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 612bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 613bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 614bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 615bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 6166057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String rating) { 6176057102dbb746593a7d59cf377c969b62e38c664Jae Seo synchronized (mLock) { 6186057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (DEBUG) { 6196057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.d(TAG, "onContentBlocked()"); 6206057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6216057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 6226057102dbb746593a7d59cf377c969b62e38c664Jae Seo return; 6236057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6246057102dbb746593a7d59cf377c969b62e38c664Jae Seo try { 6256057102dbb746593a7d59cf377c969b62e38c664Jae Seo sessionState.mClient.onContentBlocked(rating, sessionState.mSeq); 6266057102dbb746593a7d59cf377c969b62e38c664Jae Seo } catch (RemoteException e) { 6276057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.e(TAG, "error in onContentBlocked"); 6286057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6296057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6306057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6316057102dbb746593a7d59cf377c969b62e38c664Jae Seo 6326057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 633ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho public void onLayoutSurface(int left, int top, int right, int bottom) { 634ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho synchronized (mLock) { 635ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (DEBUG) { 636ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top 637ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho + ", right=" + right + ", bottom=" + bottom + ",)"); 638ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 639ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 640ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho return; 641ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 642ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho try { 643ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mClient.onLayoutSurface(left, top, right, bottom, 644ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mSeq); 645ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } catch (RemoteException e) { 646ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.e(TAG, "error in onLayoutSurface"); 647ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 648ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 649ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 650ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho 651ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho @Override 652832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 653832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 654832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 655832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 656832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 657832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 658832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 659832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 660832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 661832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 662832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 663832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 664832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 665832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 666832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 667832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 6683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 6693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 6713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 672187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim service.createSession(channels[1], callback, sessionState.mInfo.getId()); 6733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 6749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 675fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 676187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null, 677187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim null, sessionState.mSeq); 6783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6796a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 6803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 682d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 6835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 6843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 685d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 6863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 6879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 6883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 6922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 6932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 69415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee UserState userState = getUserStateLocked(userId); 69515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 69615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee setMainLocked(sessionToken, false, callingUid, userId); 69715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 6982b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 6992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 7002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 7012b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 7022b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7032b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 7043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7052b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 7063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 708fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 709fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 710abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 71115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 71215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "mainSessionToken=null"); 71315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 714abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken = null; 715abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 716abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 717abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee // Remove the session state from the global session state map of the current user. 718fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 719fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 7208d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee if (sessionState == null) { 7218d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee return; 7228d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 7238d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee 72472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 72572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 72672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 72772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 72872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 72972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 73072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 73172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 734187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 735187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 736187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 737187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 738187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 739187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 740fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 741187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 7427eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 7437eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // Log the end of watch. 7447eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo SomeArgs args = SomeArgs.obtain(); 7457eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg1 = sessionToken; 7467eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg2 = System.currentTimeMillis(); 7477eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_END, args).sendToTarget(); 748fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 749fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 75015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee private void setMainLocked(IBinder sessionToken, boolean isMain, int callingUid, int userId) { 75115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 75215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (sessionState.mHardwareSessionToken != null) { 75315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee sessionState = getSessionStateLocked(sessionState.mHardwareSessionToken, 75415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Process.SYSTEM_UID, userId); 75515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 75615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee ServiceState serviceState = getServiceStateLocked(sessionState.mInfo.getComponent(), 75715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee userId); 75815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (!serviceState.mIsHardware) { 75915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee return; 76015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 76115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee ITvInputSession session = getSessionLocked(sessionState); 76215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee try { 76315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee session.setMain(isMain); 76415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } catch (RemoteException e) { 76515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.e(TAG, "error in setMain", e); 76615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 76715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 76815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee 7698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7798e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7808e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7818e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7828e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 7838e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7848e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 7858e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7868e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7878e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7888e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 7898e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7908e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 7918e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7928e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7938e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7948e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7958e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 796969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 797969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 7988e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 799969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 800969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 801969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 802969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 803969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 804969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 805969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 806969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 807969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 808969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 809969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 8102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 811969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 8122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 813969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 8142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 818969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 819969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 820969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 821c88f1916b8ab7f5f75a00375c6fb4873ea5044afJi-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(inputState.mInfo.getComponent()); 822969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 823969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 824187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 825187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 826969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 827969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 828969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 829969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 8308e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 831969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 832969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 833969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 8343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 8353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 8373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 8393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 843969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 844969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 845969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 847969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 852b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 853b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 854b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 855b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 856b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 857b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 858b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 859b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 860b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 861b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 862b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 863b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 864b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 865b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 866b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 867b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8715c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim public List<Uri> getTvContentRatingSystemXmls(int userId) { 8725c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8735c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls"); 8745c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final long identity = Binder.clearCallingIdentity(); 8755c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim try { 8765c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim synchronized (mLock) { 8775c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim UserState userState = getUserStateLocked(resolvedUserId); 8785c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>(); 8795c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet); 8805c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim return ratingSystemXmlUriList; 8815c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8825c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } finally { 8835c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.restoreCallingIdentity(identity); 8845c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8855c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8865c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 8875c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim @Override 888969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 8893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 8913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 895969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 896969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 8978e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 898969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 8993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 907969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 9083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 9093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 9103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 913969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 914969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 9153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 922783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isParentalControlsEnabled(int userId) { 923783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 924783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isParentalControlsEnabled"); 925783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 926783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 927783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 928783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 929783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isParentalControlsEnabled(); 930783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 931783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 932783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 933783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 934783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 935783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 936783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 937783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void setParentalControlsEnabled(boolean enabled, int userId) { 938783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 939783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 940783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "setParentalControlsEnabled"); 941783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 942783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 943783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 944783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 945783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.setParentalControlsEnabled(enabled); 946783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 947783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 948783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 949783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 950783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 951783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 952783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 953783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isRatingBlocked(String rating, int userId) { 954783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 955783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isRatingBlocked"); 956783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 957783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 958783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 959783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 960783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isRatingBlocked( 961783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 962783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 963783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 964783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 965783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 966783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 967783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 968783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 969783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public List<String> getBlockedRatings(int userId) { 970783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 971783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "getBlockedRatings"); 972783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 973783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 974783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 975783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 976783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo List<String> ratings = new ArrayList<String>(); 977783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo for (TvContentRating rating 978783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo : userState.persistentDataStore.getBlockedRatings()) { 979783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ratings.add(rating.flattenToString()); 980783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 981783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return ratings; 982783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 983783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 984783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 985783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 986783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 987783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 988783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 989783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void addBlockedRating(String rating, int userId) { 990783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 991783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 992783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "addBlockedRating"); 993783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 994783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 995783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 996783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 997783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.addBlockedRating( 998783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 999783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1000783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 1001783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 1002783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1003783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1004783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1005783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1006783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void removeBlockedRating(String rating, int userId) { 1007783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 1008783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 1009783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "removeBlockedRating"); 1010783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 1011783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 1012783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 1013783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 1014783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.removeBlockedRating( 1015783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 1016783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1017783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 1018783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 1019783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1020783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1021783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1022783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private void ensureParentalControlsPermission() { 1023550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // STOPSHIP: Uncomment when b/16984416 is resolved. 1024550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo //if (mContext.checkCallingPermission( 1025550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) 1026550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // != PackageManager.PERMISSION_GRANTED) { 1027550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // throw new SecurityException( 1028550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // "The caller does not have parental controls permission"); 1029550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo //} 1030783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1031783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1032783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1033d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 10343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 10353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 10383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 1042187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 1043187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 10443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 1045187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 1046187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 10473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10482b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 10492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 10505c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 10512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 10522b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 10532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 10552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 1056187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 105772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 10582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 10602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 10612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 1063d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 10643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1065d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 1066d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 10677de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 10683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 1069187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 10703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 107915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 108015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "releaseSession(): " + sessionToken); 108115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 10823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 10853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 10893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10964c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void setMainSession(IBinder sessionToken, int userId) { 109715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 109815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "setMainSession(): " + sessionToken); 109915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 11004c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int callingUid = Binder.getCallingUid(); 11014c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11024c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userId, "setMainSession"); 11034c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final long identity = Binder.clearCallingIdentity(); 11044c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 11054c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (mLock) { 1106982abe693f66037ca265b88057eceb5a3e815182Ji-Hwan Lee UserState userState = getUserStateLocked(resolvedUserId); 1107956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (userState.mainSessionToken == sessionToken) { 11084c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return; 11094c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 111015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 111115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "mainSessionToken=" + sessionToken); 1112abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 111315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee IBinder oldMainSessionToken = userState.mainSessionToken; 11144c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userState.mainSessionToken = sessionToken; 11154c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1116956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // Inform the new main session first. 111715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee // See {@link TvInputService.Session#onSetMain}. 111815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (sessionToken != null) { 111915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee setMainLocked(sessionToken, true, callingUid, userId); 11204c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 112115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (oldMainSessionToken != null) { 112215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee setMainLocked(oldMainSessionToken, false, Process.SYSTEM_UID, userId); 11234c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11244c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11254c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } finally { 11264c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Binder.restoreCallingIdentity(identity); 11274c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11284c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11294c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 11304c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 11313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 11323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 11353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1139bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1140bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1141bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken == null) { 1142bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setSurface(surface); 1143bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } else { 1144bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1145bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setSurface(surface); 1146bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 11473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 11489a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 11493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 1152f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 1153f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 1154f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 1155f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 11563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1161e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 1162e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 1163e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 1164e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1165e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 1166e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 1167e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1168e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 1169e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1170bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1171bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1172bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).dispatchSurfaceChanged(format, width, height); 1173bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1174bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, Process.SYSTEM_UID, 1175bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId).dispatchSurfaceChanged(format, width, height); 1176bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1177e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 1178e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 1179e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1180e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1181e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 1182e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 1183e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1184e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1185e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 1186e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 11873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 1188bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_ON = 1.0f; 1189bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_OFF = 0f; 11903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 11933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1197bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1198bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1199bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setVolume(volume); 1200bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1201bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Here, we let the hardware session know only whether volume is on or 1202bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // off to prevent that the volume is controlled in the both side. 1203bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1204bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f) 1205bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF); 1206bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 12073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 12093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 12163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 12171a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) { 12183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 12193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 12213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 12223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 12243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12251a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( 12261a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim channelUri, params); 1227c22d0c0941ab65ca69977d002c4431394a735c7dJae Seo if (TvContract.isChannelUriForPassthroughInput(channelUri)) { 1228008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 1229008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 1230008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 123131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 123231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 123331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 123431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 12357eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // Log the start of watch. 123631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 12377eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg1 = sessionState.mInfo.getComponent().getPackageName(); 12387eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg2 = System.currentTimeMillis(); 12397eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg3 = ContentUris.parseId(channelUri); 12407eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg4 = params; 12417eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg5 = sessionToken; 12427eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_START, args) 12437eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo .sendToTarget(); 12443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 12463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 12473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12539a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12549a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12559bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 12569bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1257903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1258903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1259903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1260903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1261903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1262903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1263903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1264903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 12659bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1266903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1267903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1268903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1269903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1270903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1271903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1272903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1273903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1274903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1275903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 12762c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 12772c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 12782c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12792c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 12802c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 12812c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 12822c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 12832c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 12842c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 12852c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 12862c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 12872c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 12882c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12892c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12902c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 12912c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 12922c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12932c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12942c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 12952c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 129610d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void selectTrack(IBinder sessionToken, int type, String trackId, int userId) { 12971f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 12981f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12991f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 13001f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 13011f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13021f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 13031f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13041f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 130510d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo type, trackId); 13061f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 13071f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 13081f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13091f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13101f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 13111f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 13121f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13131f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13141f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 13151f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1316a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1317a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1318a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1319a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1320a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1321a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1322a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1323a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1324a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1325a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1326a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1327a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1328a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1329a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1330a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1331a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1332a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1333a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1334a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1335a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1336a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 13379a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 13389a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 13399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13409a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13419a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 13429a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13439a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13449a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13469a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13479a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 13489a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13499a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 13509a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13519a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13529a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13539a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13549a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13559a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13569a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13579a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13589a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 13599a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13609a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13619a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 13629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 13689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 13709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 13799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 13829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 13889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 13909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1396c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1397c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1398c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1399969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1400c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1401c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1402c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1403c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1404c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1405c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1406c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1407c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1408c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1409c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1410c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1411c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1412c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1413c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1414969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1415969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1416969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1417c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1418c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1419c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1420c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1421c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1422c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1423c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1424c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1425c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1426c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1427969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1428c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1429c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1430c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1431c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1432c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1433c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1434c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1435c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1436969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1437c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1438c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1439c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1440c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1441c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1442c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1443c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1444c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1445c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1446c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1447c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1448c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1449c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1450c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1451c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1452e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1453e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 1454c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) 1455c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1456c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1457c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1458c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1459c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1460c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1461c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1462c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1463c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1464c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1465c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "getAvailableTvStreamConfigList"); 1466c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1467c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.getAvailableTvStreamConfigList( 1468c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo inputId, callingUid, resolvedUserId); 1469c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1470c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1471c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1472c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1473c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1474c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1475c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config, 1476c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int userId) 1477c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1478c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1479c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1480c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1481c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1482c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1483c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1484c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1485c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1486c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1487c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "captureFrame"); 1488c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1489bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang String hardwareInputId = null; 149079124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 149179124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1492bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (userState.inputMap.get(inputId) == null) { 1493bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "Input not found for " + inputId); 1494bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang return false; 1495bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1496bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1497bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mInfo.getId().equals(inputId) 1498bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang && sessionState.mHardwareSessionToken != null) { 1499bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang hardwareInputId = userState.sessionStateMap.get( 1500bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken).mInfo.getId(); 1501bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang break; 1502bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1503bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 150479124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 1505c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.captureFrame( 1506bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang (hardwareInputId != null) ? hardwareInputId : inputId, 150779124a717c09f12c74d587d3977bf33ca37e6420Terry Heo surface, config, callingUid, resolvedUserId); 1508c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1509c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1510c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1511c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1512c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1513c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1514df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo public boolean isSingleSessionActive(int userId) throws RemoteException { 1515df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final long identity = Binder.clearCallingIdentity(); 1516df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int callingUid = Binder.getCallingUid(); 1517df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1518df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo userId, "isSingleSessionActive"); 1519df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo try { 1520df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo synchronized (mLock) { 1521df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1522df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (userState.sessionStateMap.size() == 1) { 1523df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1524df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1525df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo else if (userState.sessionStateMap.size() == 2) { 1526df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo SessionState[] sessionStates = userState.sessionStateMap.values().toArray( 1527df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo new SessionState[0]); 1528df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo // Check if there is a wrapper input. 1529df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (sessionStates[0].mHardwareSessionToken != null 1530df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo || sessionStates[1].mHardwareSessionToken != null) { 1531df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1532df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1533df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1534df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return false; 1535df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1536df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } finally { 1537df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo Binder.restoreCallingIdentity(identity); 1538df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1539df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1540df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo 1541df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo @Override 15420f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1543e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1544e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 15450f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1546e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 15470f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 15480f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1549e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1550e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1551e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1552e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1553e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1554e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1555e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1556e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1557e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1558e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1559e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1560e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1561e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1562e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1563e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1564e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1565e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1566e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1567969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1568e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 15698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 15708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1571e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1572e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1573e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1574969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1575e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1576969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1577e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1578e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1579e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1580e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1581e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1582e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1583e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1584e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1585e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1586e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1587e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1588e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1589e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1590e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1591e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1592e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1593e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1594e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1595e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1596e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1597e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1598e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1599e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1600e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1601e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1602e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1603e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1604187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1605e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1606187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1607e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1608e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1609e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1610e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1611e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1612e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1613e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1614e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1615e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1616e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1617e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1618e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1619e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1620e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1621e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1622e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1623e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1624e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1625e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1626e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1627e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1628e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1629e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1630e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1631e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1632e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1633e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1634e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1635e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1636e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1637187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1638e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1639e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1640e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1641e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1642e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1643e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1644e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1645bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang pw.println("mHardwareSessionToken: " + session.mHardwareSessionToken); 1646e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1647e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1648e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1649e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1650969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1651969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1652969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1653969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1654969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1655969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1656969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1657956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee pw.println("mainSessionToken: " + userState.mainSessionToken); 1658e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1659e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1660e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1661e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 16623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1664969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1665969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1666969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1667969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1668969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1669969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1670969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1671969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1672969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1673969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1674969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1675969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1676969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 16773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1678969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1679969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 16803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1681969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1682969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 16835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 16845c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // A set of all TV content rating system xml uris. 16855c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>(); 16865c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 168772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 168872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 168972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 169072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 16913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1692187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1693187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 16943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 16963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 16973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1698969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1699969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1700969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1701969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 170279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 17034c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // The token of a "main" TV input session. 17044c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private IBinder mainSessionToken = null; 1705783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1706783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // Persistent data store for all internal settings maintained by the TV input manager 1707783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // service. 1708783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private final PersistentDataStore persistentDataStore; 1709783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1710783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private UserState(Context context, int userId) { 1711783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo persistentDataStore = new PersistentDataStore(context, userId); 1712783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 17133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 171572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 171672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 171772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 171872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 171972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 172072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 172172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 172272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 172372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 172472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 172572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 172672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 1727a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee return mSessionTokens.isEmpty(); 172872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 172972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 173072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 173172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 173272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 173372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 173472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1735a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee // removed in releaseSessionLocked(). 173672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 173772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 173872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 173972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 174072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 174172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 174272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 174372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 174472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 174572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 174672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 174772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 1749d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1750d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 17519e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 1752187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final boolean mIsHardware; 1753187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>(); 17543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1755d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1756d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1757d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 17582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 17593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17609e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState(ComponentName component, int userId) { 17619e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 17629e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mConnection = new InputServiceConnection(component, userId); 17639e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mComponent); 17643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17672b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1768187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final TvInputInfo mInfo; 1769d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1770d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1771d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 17722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 177372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1774d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1775d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 1776bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Not null if this session represents an external device connected to a hardware TV input. 1777bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private IBinder mHardwareSessionToken; 17783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1779bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client, 1780bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang int seq, int callingUid, int userId) { 178172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 1782187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mInfo = info; 17832b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 17842b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 17852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 17862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 17872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 17882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 17892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 17902b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 17912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 17922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 17932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 17942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 17952b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 17962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 17972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 17982b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 17992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 1800bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // If there are any other sessions based on this session, they should be released. 1801bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang UserState userState = getUserStateLocked(mUserId); 1802bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 18030c38fc764b0e1c5c8b880872d9b4a647a76955cdJi-Hwan Lee if (mSessionToken == sessionState.mHardwareSessionToken) { 18044835497886ee876b16e1144d32f5bdcfbb7e9062Ji-Hwan Lee releaseSessionLocked(sessionState.mSessionToken, Process.SYSTEM_UID, 18054835497886ee876b16e1144d32f5bdcfbb7e9062Ji-Hwan Lee mUserId); 1806bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1807bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mClient.onSessionReleased(sessionState.mSeq); 1808bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1809bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in onSessionReleased", e); 1810bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1811bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1812bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 181372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 18142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 18199e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 18203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 18213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18229e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private InputServiceConnection(ComponentName component, int userId) { 18239e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 18253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 18289e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceConnected(ComponentName component, IBinder service) { 18293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 18309e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceConnected(component=" + component + ")"); 18313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1833969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 18349e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 1835d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 18363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1838187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 18399e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState.mCallback = new ServiceCallback(mComponent, mUserId); 18403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1841d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 18423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 18439a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 18443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1848d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1849d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 18503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1851969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1852187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 18539e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component) 1854187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 18558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1856187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1857187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1858187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1859187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1860187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 18614f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 18624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1863187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1864187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1865187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1866187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1867187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1868187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1869187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1870187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1871546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo List<HdmiDeviceInfo> deviceInfoList = 1872546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mTvInputHardwareManager.getHdmiDeviceList(); 1873546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo for (HdmiDeviceInfo deviceInfo : deviceInfoList) { 18744f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 1875546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 18764f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 1877546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 18784f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 18794f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1880969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 18813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 18859e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceDisconnected(ComponentName component) { 18863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 18879e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceDisconnected(component=" + component + ")"); 18883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18899e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (!mComponent.equals(component)) { 18902b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 18919e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee + mComponent + " (expected), " + component + " (actual)."); 18922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 18942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 18959e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 18962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 18972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 18982b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 18992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 19002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 19012b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 19022b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 19032b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 19042b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 19052b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 19062b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 19072b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 1908187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 19092b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19112b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1912187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19139e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component)) { 1914bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1915187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 1916187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1917187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 19189e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(mComponent, mUserId); 19192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 19259e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 19263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 19273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19289e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceCallback(ComponentName component, int userId) { 19299e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 19303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 19313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 19344f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 19354f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 19364f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 19374f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19384f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19394f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19404f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 19419e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputInfo.getId() == null || !mComponent.equals(inputInfo.getComponent())) { 19424f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 19434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19444f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19454f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19464f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 19479e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 19484f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 19494f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 19504f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19514f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19534f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 19544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19554f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 1956187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 19574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 19584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 19594f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19604f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1961187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 19624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 19638960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim public void addHdmiTvInput(int id, TvInputInfo inputInfo) { 19644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19654f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 19664f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 19678960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim mTvInputHardwareManager.addHdmiTvInput(id, inputInfo); 19684f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 19693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1970187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1971187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1972187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1973187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 19744f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 19769e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 1977187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 1978187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 1979187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 1980187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 1981187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 1982187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 1983187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 1984187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1985187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1986187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 1987187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 19884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 1989187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 1990187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 1991187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 19923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 199531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 19967eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private final class WatchLogHandler extends Handler { 19977eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // There are only two kinds of watch events that can happen on the system: 19987eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // 1. The current TV input session is tuned to a new channel. 19997eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // 2. The session is released for some reason. 20007eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // The former indicates the end of the previous log entry, if any, followed by the start of 20017eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // a new entry. The latter indicates the end of the most recent entry for the given session. 20027eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // Here the system supplies the database the smallest set of information only that is 20037eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // sufficient to consolidate the log entries while minimizing database operations in the 20047eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // system service. 20057eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private static final int MSG_LOG_WATCH_START = 1; 20067eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private static final int MSG_LOG_WATCH_END = 2; 20077eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20087eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo public WatchLogHandler(Looper looper) { 200931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 201031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 201131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 201231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 201331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 201431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 20157eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo case MSG_LOG_WATCH_START: { 201631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 20177eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo String packageName = (String) args.arg1; 20187eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo long watchStartTime = (long) args.arg2; 20197eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo long channelId = (long) args.arg3; 20207eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Bundle tuneParams = (Bundle) args.arg4; 20217eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo IBinder sessionToken = (IBinder) args.arg5; 20227eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20237eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo ContentValues values = new ContentValues(); 20247eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 20257eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 20267eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo watchStartTime); 20277eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 20287eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (tuneParams != null) { 20297eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_INTERNAL_TUNE_PARAMS, 20307eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo encodeTuneParams(tuneParams)); 20317eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo } 20327eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_INTERNAL_SESSION_TOKEN, 20337eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo sessionToken.toString()); 20347eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20357eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 203631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 203731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 203831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 20397eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo case MSG_LOG_WATCH_END: { 204031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 20417eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo IBinder sessionToken = (IBinder) args.arg1; 20427eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo long watchEndTime = (long) args.arg2; 20437eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20447eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo ContentValues values = new ContentValues(); 20457eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 20467eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo watchEndTime); 20477eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_INTERNAL_SESSION_TOKEN, 20487eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo sessionToken.toString()); 20497eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20507eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 205131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 205231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 205331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 205431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 20556a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 205631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 205731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 205831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 205931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 206031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 20617eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private String encodeTuneParams(Bundle tuneParams) { 20627eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo StringBuilder builder = new StringBuilder(); 20637eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Set<String> keySet = tuneParams.keySet(); 20647eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Iterator<String> it = keySet.iterator(); 20657eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo while (it.hasNext()) { 20667eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo String key = it.next(); 20677eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Object value = tuneParams.get(key); 20687eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (value == null) { 20697eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo continue; 207031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 20717eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(replaceEscapeCharacters(key)); 20727eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append("="); 20737eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(replaceEscapeCharacters(value.toString())); 20747eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (it.hasNext()) { 20757eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(", "); 207631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 20787eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo return builder.toString(); 207931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 208031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 20817eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private String replaceEscapeCharacters(String src) { 20827eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo final char ESCAPE_CHARACTER = '%'; 20837eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo final String ENCODING_TARGET_CHARACTERS = "%=,"; 20847eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo StringBuilder builder = new StringBuilder(); 20857eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo for (char ch : src.toCharArray()) { 20867eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (ENCODING_TARGET_CHARACTERS.indexOf(ch) >= 0) { 20877eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(ESCAPE_CHARACTER); 2088579befecb248162021929ab58ffd23f1724cc6beJae Seo } 20897eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(ch); 2090579befecb248162021929ab58ffd23f1724cc6beJae Seo } 20917eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo return builder.toString(); 2092579befecb248162021929ab58ffd23f1724cc6beJae Seo } 209331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2094969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2095187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 2096187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2097187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 2098969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2099969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 2100969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2101969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2102187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2103187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2104187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 2105187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2106187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2107187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2108187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2109187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2110187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 2111187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 2112187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2113187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 2114187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2115187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2116187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2117187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2118187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2119187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 21204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 2121187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2122187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2123187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2124187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2125187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2126187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 21274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 2128187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2129187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 2130187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2131187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2132187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2133187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2134187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2135187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2136546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) { 2137187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 21384f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 21394f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 21404f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 21414f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 21424f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2143546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 21444f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2145546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 21464f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 21474f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2148187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2149187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2150187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2151187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2152546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) { 2153187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 21544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 21554f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 21564f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 21574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 21584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2159546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceRemoved(deviceInfo); 21604f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2161546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e); 21624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 21634f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2164187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2165187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 216661daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang 216761daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang @Override 2168e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo deviceInfo) { 2169e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim synchronized (mLock) { 2170e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim Integer state = null; 2171e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim switch (deviceInfo.getDevicePowerStatus()) { 2172e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_ON: 2173e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim state = INPUT_STATE_CONNECTED; 2174e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim break; 2175e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_STANDBY: 2176e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON: 2177e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY: 2178e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim state = INPUT_STATE_CONNECTED_STANDBY; 2179e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim break; 2180e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_UNKNOWN: 2181e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim default: 2182e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim state = null; 2183e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim break; 2184e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim } 2185e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim if (state != null) { 2186e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim setStateLocked(inputId, state.intValue(), mCurrentUserId); 2187e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim } 2188e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim } 218961daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } 2190969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 21913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 2192