TvInputManagerService.java revision abca0ee7949f59e72b8d2764dafa23af18eb51db
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; 20969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED; 21969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.app.ActivityManager; 233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.BroadcastReceiver; 243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ComponentName; 255c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderOperation; 265c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderResult; 2731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentResolver; 2831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentUris; 2931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentValues; 303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Context; 313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Intent; 323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.IntentFilter; 335c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.OperationApplicationException; 343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ServiceConnection; 353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.PackageManager; 363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ResolveInfo; 373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ServiceInfo; 3831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.database.Cursor; 399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.graphics.Rect; 40187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport android.hardware.hdmi.HdmiCecDeviceInfo; 41d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputClient; 42d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardware; 43d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardwareCallback; 44d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputManager; 45969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.media.tv.ITvInputManagerCallback; 46d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputService; 47d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputServiceCallback; 48d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSession; 49d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSessionCallback; 50d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvContract; 51d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputHardwareInfo; 52d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputInfo; 53d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputService; 54c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heoimport android.media.tv.TvStreamConfig; 551f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport android.media.tv.TvTrackInfo; 563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.net.Uri; 573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Binder; 58832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 5931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Handler; 603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.IBinder; 6131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Looper; 6231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Message; 633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Process; 643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.RemoteException; 653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.UserHandle; 669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Slog; 673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.util.SparseArray; 686a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputChannel; 693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.view.Surface; 703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.internal.content.PackageMonitor; 7231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.internal.os.SomeArgs; 73e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport com.android.internal.util.IndentingPrintWriter; 7431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.server.IoThread; 753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.server.SystemService; 763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 77e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport org.xmlpull.v1.XmlPullParserException; 78e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee 79e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.FileDescriptor; 80e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport java.io.IOException; 81e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.PrintWriter; 823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.ArrayList; 833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.HashMap; 845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.HashSet; 85187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport java.util.Iterator; 863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.List; 873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.Map; 885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.Set; 893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/** This class provides a system service that manages television inputs. */ 913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopublic final class TvInputManagerService extends SystemService { 923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // STOPSHIP: Turn debugging off. 933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final boolean DEBUG = true; 943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final String TAG = "TvInputManagerService"; 953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Context mContext; 97c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareManager mTvInputHardwareManager; 983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final ContentResolver mContentResolver; 10031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A global lock. 1023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Object mLock = new Object(); 1033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // ID of the current user. 1053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int mCurrentUserId = UserHandle.USER_OWNER; 1063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A map from user id to UserState. 1083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 1093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final Handler mLogHandler; 11131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 11731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler = new LogHandler(IoThread.get().getLooper()); 11831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 119187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); 12031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(mCurrentUserId, new UserState()); 1233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onStart() { 1283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo publishBinderService(Context.TV_INPUT_SERVICE, new BinderService()); 1293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1310ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee @Override 1320ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee public void onBootPhase(int phase) { 1330ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1340ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee registerBroadcastReceivers(); 135187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 1360ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee synchronized (mLock) { 1370ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee buildTvInputListLocked(mCurrentUserId); 1380ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1390ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 140969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.onBootPhase(phase); 1410ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1420ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee 1433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void registerBroadcastReceivers() { 1443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageMonitor monitor = new PackageMonitor() { 1453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSomePackagesChanged() { 1473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(mCurrentUserId); 1493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1515c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1525c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo @Override 1535c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo public void onPackageRemoved(String packageName, int uid) { 1545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo synchronized (mLock) { 1555c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo UserState userState = getUserStateLocked(mCurrentUserId); 156969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (!userState.packageSet.contains(packageName)) { 1575c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo // Not a TV input package. 1585c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo return; 1595c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1605c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1615c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1625c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ArrayList<ContentProviderOperation> operations = 1635c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo new ArrayList<ContentProviderOperation>(); 1645c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1655c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; 1665c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String[] selectionArgs = { packageName }; 1675c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1685c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI) 1695c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1705c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI) 1715c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation 1735c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .newDelete(TvContract.WatchedPrograms.CONTENT_URI) 1745c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1755c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1765c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ContentProviderResult[] results = null; 1775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo try { 1785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations); 1795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } catch (RemoteException | OperationApplicationException e) { 1805c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.e(TAG, "error in applyBatch" + e); 1815c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo if (DEBUG) { 1845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid 1855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo + ")"); 1865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "results=" + results); 1875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 1903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo monitor.register(mContext, null, UserHandle.ALL, true); 1913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo IntentFilter intentFilter = new IntentFilter(); 1933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 1943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext.registerReceiverAsUser(new BroadcastReceiver() { 1963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onReceive(Context context, Intent intent) { 1983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String action = intent.getAction(); 1993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (Intent.ACTION_USER_SWITCHED.equals(action)) { 2003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 2023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }, UserHandle.ALL, intentFilter, null, null); 2063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 208187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean hasHardwarePermission(PackageManager pm, ComponentName name) { 209187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, 210187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim name.getPackageName()) == PackageManager.PERMISSION_GRANTED; 211187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 212187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void buildTvInputListLocked(int userId) { 2143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 215969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2168e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 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 } 232e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee try { 2334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.clear(); 234187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ComponentName service = new ComponentName(si.packageName, si.name); 235187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (hasHardwarePermission(pm, service)) { 236187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(service); 237187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState == null) { 238187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // We see this hardware TV input service for the first time; we need to 239187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // prepare the ServiceState object so that we can connect to the service and 240187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // let it add TvInputInfo objects to mInputList if there's any. 241187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(service, userId); 242187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(service, serviceState); 243187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2444f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.addAll(serviceState.mInputList); 245187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 246187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2474f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); 248187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 249187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2504f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (TvInputInfo info : inputList) { 251187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (DEBUG) Slog.d(TAG, "add " + info.getId()); 2528e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim TvInputState state = userState.inputMap.get(info.getId()); 253187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (state == null) { 254187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state = new TvInputState(); 255187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 256187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state.mInfo = info; 2578e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim inputMap.put(info.getId(), state); 258969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 259226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 260226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Reconnect the service if existing input is updated. 261187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(service, userId); 262187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 263187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.packageSet.add(si.packageName); 264e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } catch (IOException | XmlPullParserException e) { 265e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee Slog.e(TAG, "Can't load TV input " + si.name, e); 266e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 2673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2688e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : inputMap.keySet()) { 2708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!userState.inputMap.containsKey(inputId)) { 2718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputAddedLocked(userState, inputId); 2728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : userState.inputMap.keySet()) { 2768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!inputMap.containsKey(inputId)) { 2778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputRemovedLocked(userState, inputId); 2788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2798e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2808e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2818e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap.clear(); 2828e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap = inputMap; 2833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 2863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 2873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 2883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 2893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 2913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 2923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 2933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 2953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 2963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState = new UserState(); 2973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 2993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 3043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 305b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 306b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 307b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 308b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 3103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 311d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 3123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 313d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 3143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 3203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 3223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 323d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 3243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 325d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 3263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 3283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 33072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.clear(); 331d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 3323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 3343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 33572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 33672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 3373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 3383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 349187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private ServiceState getServiceStateLocked(ComponentName name, int userId) { 3503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 351187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(name); 3523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 353187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim throw new IllegalStateException("Service state not found for " + name + " (userId=" 3547de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 366d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3702b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3744c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return getSessionLocked(getSessionStateLocked(sessionToken, callingUid, userId)); 3754c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 3764c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 3774c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private ITvInputSession getSessionLocked(SessionState sessionState) { 378d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3804c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee throw new IllegalStateException("Session not yet created for token " 3814c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee + sessionState.mSessionToken); 3823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 3843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 3873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 3883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 3893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 3903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 392187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean shouldMaintainConnection(ServiceState serviceState) { 393187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return !serviceState.mClientTokens.isEmpty() 394187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || !serviceState.mSessionTokens.isEmpty() 395187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || serviceState.mIsHardware; 396187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // TODO: Find a way to maintain connection only when necessary. 397187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 398187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 399187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private void updateServiceConnectionLocked(ComponentName service, int userId) { 4003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 401187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(service); 4023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 4033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4052b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting) { 4062b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!serviceState.mSessionTokens.isEmpty()) { 4072b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // wait until all the sessions are removed. 4082b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 4092b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 4102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = false; 4112b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 412187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean maintainConnection = shouldMaintainConnection(serviceState); 413187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mService == null && maintainConnection && userId == mCurrentUserId) { 4143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is not yet connected but its state indicates that we 4153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // have pending requests. Then, connect the service. 416d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mBound) { 4173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // We have already bound to the service so we don't try to bind again until after we 4183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // unbind later on. 4193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 422187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "bindServiceAsUser(service=" + service + ", userId=" + userId + ")"); 4233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 424d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim 425187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(service); 426226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Binding service may fail if the service is updating. 427226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // In that case, the connection will be revived in buildTvInputListLocked called by 428226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // onSomePackagesChanged. 429e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee serviceState.mBound = mContext.bindServiceAsUser( 430e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); 431187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (serviceState.mService != null && !maintainConnection) { 4323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is already connected but its state indicates that we have 4333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // nothing to do with it. Then, disconnect the service. 4343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 435187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "unbindService(service=" + service + ")"); 4363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 437d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 438187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.remove(service); 4393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 44272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 44372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 44472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 44572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 44672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 44772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 44872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 44972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 45072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 45172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 45272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 45372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4557de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 45672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 45772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 459187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")"); 4603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4616a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4626a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4636a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 4673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSessionCreated(ITvInputSession session) { 4683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 469187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")"); 4703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 472d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 473fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 474fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 475187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 476187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 477fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 4782b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 4792b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 4802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 4812b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 4822b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 48372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 48472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 48572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 48672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 48772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 48872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 48972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 49072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 491187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 492187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), sessionToken, channels[0], 493187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mSeq); 494fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 4956a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 4963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 498832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 499832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 5001f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 501a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 502a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5031f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 504a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 505a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 506a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 507a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 508a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5091f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 5101f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 5111f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 5121f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 5131f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 514a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5151f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 516a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 517a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 518a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 519a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 520a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 5211f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onTrackInfoChanged(List<TvTrackInfo> tracks) { 522a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 523a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onTrackInfoChanged(" + tracks + ")"); 525a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 526a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 527a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 528a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 529a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5301f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onTrackInfoChanged(tracks, 531a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang sessionState.mSeq); 532a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5331f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onTrackInfoChanged"); 534b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 535b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 536b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 537b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 538b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 5399b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 5409b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5419b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5429b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 5439b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5449b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5459b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5469b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5479b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5489b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 5499b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5509b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5519b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5529b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5539b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5549b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5559b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 5569b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 5579b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5589b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5599b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 5609b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5619b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5629b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5639b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5649b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5659b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 5669b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5679b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 5689b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5699b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5709b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5719b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5729b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 573bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed() { 574bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo synchronized (mLock) { 575bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 576bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.d(TAG, "onContentAllowed()"); 577bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 578bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 579bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo return; 580bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 581bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo try { 582bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo sessionState.mClient.onContentAllowed(sessionState.mSeq); 583bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } catch (RemoteException e) { 584bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.e(TAG, "error in onContentAllowed"); 585bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 586bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 587bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 588bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 589bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 5906057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String rating) { 5916057102dbb746593a7d59cf377c969b62e38c664Jae Seo synchronized (mLock) { 5926057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (DEBUG) { 5936057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.d(TAG, "onContentBlocked()"); 5946057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 5956057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 5966057102dbb746593a7d59cf377c969b62e38c664Jae Seo return; 5976057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 5986057102dbb746593a7d59cf377c969b62e38c664Jae Seo try { 5996057102dbb746593a7d59cf377c969b62e38c664Jae Seo sessionState.mClient.onContentBlocked(rating, sessionState.mSeq); 6006057102dbb746593a7d59cf377c969b62e38c664Jae Seo } catch (RemoteException e) { 6016057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.e(TAG, "error in onContentBlocked"); 6026057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6036057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6046057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6056057102dbb746593a7d59cf377c969b62e38c664Jae Seo 6066057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 607832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 608832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 609832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 610832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 611832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 612832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 613832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 614832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 615832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 616832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 617832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 618832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 619832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 620832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 621832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 622832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 6233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 6243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 6263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 627187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim service.createSession(channels[1], callback, sessionState.mInfo.getId()); 6283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 6299a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 630fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 631187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null, 632187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim null, sessionState.mSeq); 6333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6346a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 6353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 637d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 6385c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 6393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 640d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 6413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 6429a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 6433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6442b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6462b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 6472b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 6482b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 6492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 6502b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 6512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 6522b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 6532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 6553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 6573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 659fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 660fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 661abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 662abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken = null; 663abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 664abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 665abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee // Remove the session state from the global session state map of the current user. 666fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 667fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 66831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry, if any. 669d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 67031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 671d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 67231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = System.currentTimeMillis(); 67331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget(); 67431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 67531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 67672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 67772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 67872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 67972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 68072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 68172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 68272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 68372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 68472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 68572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 686187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 687187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 688187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 689187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 690187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 691187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 692fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 693187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 694fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 695fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 696969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void unregisterClientInternalLocked(IBinder clientToken, String inputId, 69772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim int userId) { 69872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 69972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 70072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 70172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mInputIds.remove(inputId); 70272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 70372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(clientToken); 70472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 70572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 70672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 707187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 708187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info == null) { 709187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return; 710187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 711187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 71272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (serviceState == null) { 71372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 71472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 71572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 71672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Remove this client from the client list and unregister the callback. 71772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.remove(clientToken); 71872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (!serviceState.mClientTokens.isEmpty()) { 71972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // We have other clients who want to keep the callback. Do this later. 72072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 72172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 72272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (serviceState.mService == null || serviceState.mCallback == null) { 72372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 72472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 72572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 72672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 72772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 72872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "error in unregisterCallback", e); 72972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } finally { 73072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mCallback = null; 731187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), userId); 73272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 7358e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7368e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7378e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7388e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7398e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7408e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7418e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7428e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7438e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7448e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7458e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7468e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7478e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7488e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 7498e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7508e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 7518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7528e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7538e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7548e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 7558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7568e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 7578e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7588e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7598e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7608e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7618e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 762969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 763969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 7648e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 765969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 766969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 767969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 768969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 769969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 770969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 771969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 772969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 773969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 774969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 775969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 7762b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 777969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 7782b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 779969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 7802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7812b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7822b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7832b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 784969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 785969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 786969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 787969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(inputId); 788969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 789969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 790187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 791187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 792969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 793969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 794969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 795969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 7968e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 797969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 798969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 799969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 8003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 8013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 8033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 8053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 809969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 810969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 811969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 813969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 818b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 819b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 820b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 821b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 822b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 823b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 824b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 825b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 826b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 827b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 828b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 829b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 830b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 831b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 832b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 833b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 837969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 8383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 8403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 844969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 845969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 8468e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 847969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 8483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 856969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 8573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 8593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 862969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 863969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 8643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 871d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 8723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 8733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 8743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 8753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 8763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 880187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 881187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 8823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 883187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 884187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 8853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 8872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 8885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 8892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 8902b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 8922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 8932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 894187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 89572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 8962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 8972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 8982b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 8992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 9002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 901d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 9023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 903d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 904d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 9057de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 9063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 907187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 9083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 9163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 9173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 9183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 9203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 9232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 9243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 9314c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void setMainSession(IBinder sessionToken, int userId) { 9324c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int callingUid = Binder.getCallingUid(); 9334c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9344c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userId, "setMainSession"); 9354c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final long identity = Binder.clearCallingIdentity(); 9364c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 9374c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (mLock) { 938982abe693f66037ca265b88057eceb5a3e815182Ji-Hwan Lee UserState userState = getUserStateLocked(resolvedUserId); 9394c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee if (sessionToken == userState.mainSessionToken) { 9404c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return; 9414c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 9424c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 9434c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 9444c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee resolvedUserId); 9454c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked( 9464c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee sessionState.mInfo.getComponent(), resolvedUserId); 9474c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee ITvInputSession session = getSessionLocked(sessionState); 9484c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 949abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee ServiceState prevMainServiceState = null; 950abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee ITvInputSession prevMainSession = null; 951abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (userState.mainSessionToken != null) { 952abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee SessionState prevMainSessionState = getSessionStateLocked( 953abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId); 954abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee prevMainServiceState = getServiceStateLocked( 955abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee prevMainSessionState.mInfo.getComponent(), resolvedUserId); 956abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee prevMainSession = getSessionLocked(prevMainSessionState); 957abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 958abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 9594c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userState.mainSessionToken = sessionToken; 9604c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 9614c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // Inform the new main session first. See {@link TvInputService#onSetMain}. 9624c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee if (serviceState.mIsHardware) { 9634c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 9644c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee session.setMainSession(true); 9654c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 9664c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 9674c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 9684c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 969abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (prevMainSession != null && prevMainServiceState.mIsHardware) { 9704c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 9714c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee prevMainSession.setMainSession(false); 9724c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 9734c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 9744c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 9754c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 9764c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 9774c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } finally { 9784c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Binder.restoreCallingIdentity(identity); 9794c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 9804c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 9814c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 9824c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 9833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 9843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 9853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 9873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 9903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).setSurface( 9923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo surface); 9933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 9949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 9953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 998f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 999f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 1000f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 1001f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 10023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1007e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 1008e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 1009e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 1010e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1011e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 1012e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 1013e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1014e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 1015e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1016e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 1017e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho .dispatchSurfaceChanged(format, width, height); 1018e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 1019e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 1020e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1021e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1022e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 1023e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 1024e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1025e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1026e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 1027e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 10283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 10293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 10323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).setVolume( 10373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo volume); 10383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 10399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 10403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void tune(IBinder sessionToken, final Uri channelUri, int userId) { 10493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 10523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(channelUri); 1057008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho if (TvContract.isChannelUriForPassthroughTvInput(channelUri)) { 1058008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 1059008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 1060008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 106131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long currentTime = System.currentTimeMillis(); 106231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = ContentUris.parseId(channelUri); 106331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 106431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry first, if any. 106531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 106631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 1067d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 106831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1069d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 107031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = currentTime; 107131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args) 107231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo .sendToTarget(); 107331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 107431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 107531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Create a log entry and fill it later. 1076187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim String packageName = sessionState.mInfo.getServiceInfo().packageName; 107731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 10785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 1079f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 108031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo currentTime); 1081f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 1082f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 108331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1084d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mLogUri = mContentResolver.insert( 108531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo TvContract.WatchedPrograms.CONTENT_URI, values); 108631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1087d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 108831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = ContentUris.parseId(channelUri); 108931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = currentTime; 109031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget(); 10913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 10929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 10933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 10943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 11019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 11029bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 11039bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1104903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1105903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1106903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1107903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1108903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1109903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1110903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1111903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 11129bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1113903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1114903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1115903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1116903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1117903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1118903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1119903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1120903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1121903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1122903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 11232c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 11242c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 11252c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11262c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 11272c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 11282c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 11292c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 11302c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 11312c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 11322c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 11332c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 11342c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 11352c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 11362c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 11372c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 11382c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 11392c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 11402c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 11412c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 11422c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 11431f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void selectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 11441f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 11451f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11461f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 11471f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 11481f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 11491f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 11501f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 11511f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 11521f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 11531f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 11541f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 11551f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11561f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11571f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 11581f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 11591f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11601f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11611f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 11621f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 11631f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void unselectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 11641f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 11651f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11661f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "unselectTrack"); 11671f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 11681f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 11691f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 11701f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 11711f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).unselectTrack( 11721f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 11731f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 11741f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in unselectTrack", e); 11751f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11761f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11771f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 11781f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 11791f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11801f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11811f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 11821f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1183a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1184a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1185a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1186a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1187a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1188a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1189a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1190a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1191a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1192a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1193a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1194a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1195a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1196a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1197a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1198a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1199a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1200a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1201a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1202a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1203a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 12049a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 12059a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 12069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 12079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 12099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 12109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 12119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 12129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 12139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 12149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 12159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 12169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 12179a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12189a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12199a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 12209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 12219a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12229a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12239a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12249a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12259a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 12269a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 12279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12289a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 12299a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 12309a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 12319a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 12329a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 12339a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 12349a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 12359a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 12369a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 12379a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12389a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 12409a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 12419a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12429a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12439a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12449a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 12469a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 12479a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12489a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 12499a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 12509a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 12519a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 12529a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 12539a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 12549a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 12559a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 12569a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 12579a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12589a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12599a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 12609a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 12619a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1263c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1264c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1265c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1266969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1267c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1268c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1269c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1270c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1271c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1272c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1273c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1274c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1275c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1276c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1277c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1278c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1279c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1280c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1281969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1282969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1283969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1284c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1285c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1286c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1287c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1288c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1289c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1290c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1291c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1292c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1293c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1294969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1295c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1296c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1297c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1298c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1299c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1300c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1301c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1302c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1303969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1304c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1305c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1306c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1307c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1308c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1309c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1310c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1311c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1312c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1313c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1314c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1315c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1316c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1317c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1318c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1319e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1320e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 1321c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) 1322c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1323c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1324c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1325c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1326c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1327c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1328c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1329c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1330c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1331c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1332c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "getAvailableTvStreamConfigList"); 1333c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1334c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.getAvailableTvStreamConfigList( 1335c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo inputId, callingUid, resolvedUserId); 1336c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1337c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1338c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1339c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1340c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1341c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1342c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config, 1343c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int userId) 1344c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1345c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1346c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1347c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1348c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1349c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1350c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1351c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1352c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1353c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1354c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "captureFrame"); 1355c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 135679124a717c09f12c74d587d3977bf33ca37e6420Terry Heo final String wrappedInputId; 135779124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 135879124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 135979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo wrappedInputId = userState.wrappedInputMap.get(inputId); 136079124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 1361c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.captureFrame( 136279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo (wrappedInputId != null) ? wrappedInputId : inputId, 136379124a717c09f12c74d587d3977bf33ca37e6420Terry Heo surface, config, callingUid, resolvedUserId); 1364c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1365c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1366c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1367c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1368c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1369c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 13700f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1371e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1372e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 13730f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1374e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 13750f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 13760f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1377e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1378e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1379e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1380e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1381e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1382e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1383e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1384e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1385e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1386e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1387e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1388e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1389e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1390e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1391e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1392e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1393e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1394e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1395969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1396e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 13978e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 13988e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1399e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1400e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1401e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1402969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1403e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1404969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1405e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1406e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1407e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1408e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1409e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1410e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1411e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1412e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1413e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1414e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1415e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1416e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1417e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1418e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mInputIds:"); 1419e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1420e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (String inputId : client.mInputIds) { 1421e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(inputId); 1422e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1423e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1424e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1425e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1426e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1427e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1428e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1429e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1430e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1431e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1432e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1433e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1434e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1435e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1436e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1437e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1438e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1439187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1440e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1441187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1442e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1443e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1444e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1445e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1446e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1447e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1448e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens:"); 1449e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1450e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mClientTokens) { 1451e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1452e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1453e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1454e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1455e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1456e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1457e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1458e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1459e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1460e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1461e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1462e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1463e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1464e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1465e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1466e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1467e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1468e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1469e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1470e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1471e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1472e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1473e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1474e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1475e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1476e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1477e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1478e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1479187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1480e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1481e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1482e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1483e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1484e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1485e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1486e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1487e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1488e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1489e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1490e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1491969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1492969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1493969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1494969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1495969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1496969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1497969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1498e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1499e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1500e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1501e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 15023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1504969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1505969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1506969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1507969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1508969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1509969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1510969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1511969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1512969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1513969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1514969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1515969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1516969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 15173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1518969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1519969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 15203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1521969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1522969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 15235c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 152472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 152572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 152672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 152772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 15283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1529187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1530187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 15313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 15323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 15333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 15343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1535969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1536969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1537969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1538969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 153979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 154079124a717c09f12c74d587d3977bf33ca37e6420Terry Heo // A mapping from the TV input id to wrapped input id. 154179124a717c09f12c74d587d3977bf33ca37e6420Terry Heo private final Map<String, String> wrappedInputMap = new HashMap<String, String>(); 15424c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 15434c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // The token of a "main" TV input session. 15444c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private IBinder mainSessionToken = null; 15453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 154772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 154872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<String> mInputIds = new ArrayList<String>(); 154972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 155072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 155172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 155272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 155372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 155472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 155572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 155672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 155772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 155872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 155972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 156072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return mInputIds.isEmpty() && mSessionTokens.isEmpty(); 156172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 156272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 156372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 156472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 156572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 156672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 156772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1568969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // removed in releaseSessionLocked() or unregisterClientInternalLocked(). 156972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 157072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 157172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 157272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 157372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 157472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 157572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mInputIds.size() > 0) { 1576969167dc05a6485a32d160895871cff46fd81884Wonsik Kim unregisterClientInternalLocked( 157772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken, clientState.mInputIds.get(0), mUserId); 157872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 157972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 158072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 158172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 158272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 158372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 158472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 15853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 158672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); 1587d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1588d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 1589187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final ComponentName mName; 1590187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final boolean mIsHardware; 1591187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>(); 15923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1593d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1594d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1595d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 15962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 15973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1598187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private ServiceState(ComponentName name, int userId) { 1599187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mName = name; 1600187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mConnection = new InputServiceConnection(name, userId); 1601187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mName); 16023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16052b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1606187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final TvInputInfo mInfo; 1607d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1608d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1609d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 16102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 161172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1612d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1613d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 16143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1615187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client, int seq, 16162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim int callingUid, int userId) { 161772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 1618187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mInfo = info; 16192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 16202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 16212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 16222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 16232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 16252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 16262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 16272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 16282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 16292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 16302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 16312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 16322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 16332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 16342b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 163672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 16372b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 1642187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final ComponentName mName; 16433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 16443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1645187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private InputServiceConnection(ComponentName name, int userId) { 1646187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mName = name; 16473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 16483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 16513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onServiceConnected(ComponentName name, IBinder service) { 16523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 1653187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onServiceConnected(name=" + name + ")"); 16543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1656969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 1657187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(mName); 1658d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 16593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1661187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 1662187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mCallback = new ServiceCallback(mName, mUserId); 16633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1664d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 16653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 16669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 16673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1671d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1672d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 16733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1674969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1675187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 1676187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (inputState.mInfo.getComponent().equals(name) 1677187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 16788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1679187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1680187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1681187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1682187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1683187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 16844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 16854f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1686187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1687187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1688187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1689187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1690187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1691187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1692187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1693187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 16944f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<HdmiCecDeviceInfo> cecDeviceInfoList = 16954f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHdmiCecInputDeviceList(); 16964f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (HdmiCecDeviceInfo cecDeviceInfo : cecDeviceInfoList) { 16974f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 16984f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 16994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 17004f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 17014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 17024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1703969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 17043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 17083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onServiceDisconnected(ComponentName name) { 17093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 1710187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onServiceDisconnected(name=" + name + ")"); 17113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1712187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!mName.equals(name)) { 17132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 1714187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim + mName + " (expected), " + name + " (actual)."); 17152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 17162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 17172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 1718187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(mName); 17192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 17202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 17212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 17222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 17232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 17242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 17252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 17262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 17272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 17282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 17292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 17302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 1731187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 17322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 17332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 17342b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1735187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 1736187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (inputState.mInfo.getComponent().equals(name)) { 173779124a717c09f12c74d587d3977bf33ca37e6420Terry Heo String inputId = inputState.mInfo.getId(); 173879124a717c09f12c74d587d3977bf33ca37e6420Terry Heo notifyInputStateChangedLocked(userState, inputId, 1739187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 174079124a717c09f12c74d587d3977bf33ca37e6420Terry Heo userState.wrappedInputMap.remove(inputId); 1741187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1742187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1743187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(mName, mUserId); 17442b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 17452b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 17463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 1750187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final ComponentName mName; 17513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 17523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1753187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceCallback(ComponentName name, int userId) { 1754187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mName = name; 17553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 17563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 17594f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 17604f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 17614f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 17624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 17634f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 17644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 17654f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 17664f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (inputInfo.getId() == null || !mName.equals(inputInfo.getComponent())) { 17674f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 17684f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 17694f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 17704f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 17714f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 17724f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ServiceState serviceState = getServiceStateLocked(mName, mUserId); 17734f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 17744f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 17754f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 17764f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 17773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 17784f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 17794f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 17804f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 1781187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 17824f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 17834f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 17844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 17854f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1786187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 17874f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 17884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHdmiCecTvInput(int logicalAddress, TvInputInfo inputInfo) { 17894f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 17904f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 17914f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 17924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHdmiCecTvInput(logicalAddress, inputInfo); 17934f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 17943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1795187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1796187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1797187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1798187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 17994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 18003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1801187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = getServiceStateLocked(mName, mUserId); 1802187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 1803187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 1804187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 1805187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 1806187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 1807187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 1808187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 1809187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1810187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1811187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 1812187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 18134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 1814187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 1815187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 1816187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 18173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 181979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 182079124a717c09f12c74d587d3977bf33ca37e6420Terry Heo @Override 182179124a717c09f12c74d587d3977bf33ca37e6420Terry Heo public void setWrappedInputId(String inputId, String wrappedInputId) { 182279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 182379124a717c09f12c74d587d3977bf33ca37e6420Terry Heo if (!hasInputIdLocked(inputId)) { 182479124a717c09f12c74d587d3977bf33ca37e6420Terry Heo return; 182579124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 182679124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(mUserId); 182779124a717c09f12c74d587d3977bf33ca37e6420Terry Heo userState.wrappedInputMap.put(inputId, wrappedInputId); 182879124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 182979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 183079124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 183179124a717c09f12c74d587d3977bf33ca37e6420Terry Heo private boolean hasInputIdLocked(String inputId) { 183279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo ServiceState serviceState = getServiceStateLocked(mName, mUserId); 183379124a717c09f12c74d587d3977bf33ca37e6420Terry Heo for (TvInputInfo inputInfo : serviceState.mInputList) { 183479124a717c09f12c74d587d3977bf33ca37e6420Terry Heo if (inputInfo.getId().equals(inputId)) { 183579124a717c09f12c74d587d3977bf33ca37e6420Terry Heo return true; 183679124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 183779124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 183879124a717c09f12c74d587d3977bf33ca37e6420Terry Heo return false; 183979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 18403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 184131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 184231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final class LogHandler extends Handler { 184331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_OPEN_ENTRY = 1; 184431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_UPDATE_ENTRY = 2; 184531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_CLOSE_ENTRY = 3; 184631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 184731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public LogHandler(Looper looper) { 184831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 184931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 185031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 185131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 185231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 185331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 185431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_OPEN_ENTRY: { 185531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 185631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 185731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 185831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 185931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 186031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 186131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 186231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 186331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_UPDATE_ENTRY: { 186431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 186531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 186631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 186731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 186831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onUpdateEntry(uri, channelId, time); 186931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 187031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 187131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 187231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_CLOSE_ENTRY: { 187331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 187431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 187531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg2; 187631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onCloseEntry(uri, time); 187731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 187831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 187931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 188031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 18816a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 188231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 188331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 188431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 188531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 188631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 188731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onOpenEntry(Uri uri, long channelId, long watchStarttime) { 188831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 1889f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_TITLE, 1890f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, 1891f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, 1892bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcbJae Seo TvContract.Programs.COLUMN_SHORT_DESCRIPTION 189331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 1894f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " 1895f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND " 1896f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + ">?"; 189731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] selectionArgs = { 189831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(channelId), 189931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime), 190031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime) 190131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 1902f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String sortOrder = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + " ASC"; 190331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 190431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 190531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection, 190631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo selection, selectionArgs, sortOrder); 190731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 190831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1909f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, cursor.getString(0)); 1910f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 1911f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo cursor.getLong(1)); 191231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(2); 1913f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 1914f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3)); 191531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 191631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 191731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Schedule an update when the current program ends. 191831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 191931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg1 = uri; 192031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = channelId; 192131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = endTime; 192231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args); 192331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo sendMessageDelayed(msg, endTime - System.currentTimeMillis()); 192431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 192531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 192631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 192731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 192831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 192931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 193031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 193131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 193231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onUpdateEntry(Uri uri, long channelId, long time) { 193331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 1934f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 1935f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 1936f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_TITLE, 1937f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 1938f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, 1939f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_DESCRIPTION 194031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 194131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 194231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 194331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(uri, projection, null, null, null); 194431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 194531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchStartTime = cursor.getLong(0); 194631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchEndTime = cursor.getLong(1); 194731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String title = cursor.getString(2); 194831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long startTime = cursor.getLong(3); 194931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(4); 195031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String description = cursor.getString(5); 195131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 195231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Do nothing if the current log entry is already closed. 195331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (watchEndTime > 0) { 195431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 195531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 195631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 195731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // The current program has just ended. Create a (complete) log entry off the 195831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // current entry. 195931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1960f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 196131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo watchStartTime); 1962f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, time); 1963f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 1964f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, title); 1965f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, startTime); 1966f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 1967f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, description); 196831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 196931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 197031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 197131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 197231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 197331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 197431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 197531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Re-open the current log entry with the next program information. 197631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 197731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 197831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 197931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onCloseEntry(Uri uri, long watchEndTime) { 198031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1981f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime); 198231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 198331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 198431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 1985969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1986187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 1987187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1988187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 1989969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 1990969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 1991969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1992969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1993187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1994187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1995187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 1996187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 1997187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 1998187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 1999187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2000187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2001187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 2002187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 2003187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2004187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 2005187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2006187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2007187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2008187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2009187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2010187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 20114f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 2012187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2013187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2014187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2015187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2016187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2017187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 20184f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 2019187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2020187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 2021187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2022187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2023187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2024187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2025187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2026187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 20274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDeviceInfo) { 2028187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 20294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 20304f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 20314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 20324f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 20334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 20344f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 20354f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 20364f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 20374f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20384f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2039187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2040187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2041187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2042187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 20434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDeviceInfo) { 2044187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 20454f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 20464f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 20474f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 20484f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 20494f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 20504f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceRemoved(cecDeviceInfo); 20514f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 20524f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceRemoved", e); 20534f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2055187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2056187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2057969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 20583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 2059