TvInputManagerService.java revision 008f6d4e326f6372e165bdf342178ecd1e834e2f
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; 541f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport android.media.tv.TvTrackInfo; 553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.net.Uri; 563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Binder; 57832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 5831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Handler; 593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.IBinder; 6031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Looper; 6131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Message; 623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Process; 633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.RemoteException; 643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.UserHandle; 659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Slog; 663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.util.SparseArray; 676a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputChannel; 683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.view.Surface; 693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.internal.content.PackageMonitor; 7131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.internal.os.SomeArgs; 72e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport com.android.internal.util.IndentingPrintWriter; 7331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.server.IoThread; 743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.server.SystemService; 753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 76e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport org.xmlpull.v1.XmlPullParserException; 77e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee 78e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.FileDescriptor; 79e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport java.io.IOException; 80e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.PrintWriter; 813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.ArrayList; 823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.HashMap; 835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.HashSet; 84187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport java.util.Iterator; 853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.List; 863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.Map; 875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.Set; 883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/** This class provides a system service that manages television inputs. */ 903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopublic final class TvInputManagerService extends SystemService { 913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // STOPSHIP: Turn debugging off. 923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final boolean DEBUG = true; 933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final String TAG = "TvInputManagerService"; 943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Context mContext; 96c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareManager mTvInputHardwareManager; 973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final ContentResolver mContentResolver; 9931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A global lock. 1013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Object mLock = new Object(); 1023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // ID of the current user. 1043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int mCurrentUserId = UserHandle.USER_OWNER; 1053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A map from user id to UserState. 1073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 1083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final Handler mLogHandler; 11031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 11631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler = new LogHandler(IoThread.get().getLooper()); 11731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 118187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); 11931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(mCurrentUserId, new UserState()); 1223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onStart() { 1273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo publishBinderService(Context.TV_INPUT_SERVICE, new BinderService()); 1283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1300ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee @Override 1310ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee public void onBootPhase(int phase) { 1320ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1330ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee registerBroadcastReceivers(); 134187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 1350ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee synchronized (mLock) { 1360ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee buildTvInputListLocked(mCurrentUserId); 1370ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1380ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 139969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.onBootPhase(phase); 1400ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1410ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee 1423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void registerBroadcastReceivers() { 1433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageMonitor monitor = new PackageMonitor() { 1443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSomePackagesChanged() { 1463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(mCurrentUserId); 1483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1505c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1515c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo @Override 1525c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo public void onPackageRemoved(String packageName, int uid) { 1535c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo synchronized (mLock) { 1545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo UserState userState = getUserStateLocked(mCurrentUserId); 155969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (!userState.packageSet.contains(packageName)) { 1565c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo // Not a TV input package. 1575c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo return; 1585c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1595c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1605c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1615c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ArrayList<ContentProviderOperation> operations = 1625c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo new ArrayList<ContentProviderOperation>(); 1635c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1645c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; 1655c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String[] selectionArgs = { packageName }; 1665c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1675c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI) 1685c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1695c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI) 1705c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1715c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation 1725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .newDelete(TvContract.WatchedPrograms.CONTENT_URI) 1735c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1745c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1755c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ContentProviderResult[] results = null; 1765c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo try { 1775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations); 1785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } catch (RemoteException | OperationApplicationException e) { 1795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.e(TAG, "error in applyBatch" + e); 1805c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1815c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo if (DEBUG) { 1835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid 1845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo + ")"); 1855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "results=" + results); 1865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 1893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo monitor.register(mContext, null, UserHandle.ALL, true); 1903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo IntentFilter intentFilter = new IntentFilter(); 1923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 1933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext.registerReceiverAsUser(new BroadcastReceiver() { 1953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onReceive(Context context, Intent intent) { 1973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String action = intent.getAction(); 1983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (Intent.ACTION_USER_SWITCHED.equals(action)) { 1993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 2013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }, UserHandle.ALL, intentFilter, null, null); 2053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 207187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean hasHardwarePermission(PackageManager pm, ComponentName name) { 208187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, 209187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim name.getPackageName()) == PackageManager.PERMISSION_GRANTED; 210187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 211187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void buildTvInputListLocked(int userId) { 2133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 214969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2158e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 216969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.packageSet.clear(); 2173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2189a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (DEBUG) Slog.d(TAG, "buildTvInputList"); 2193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageManager pm = mContext.getPackageManager(); 2203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo List<ResolveInfo> services = pm.queryIntentServices( 221e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee new Intent(TvInputService.SERVICE_INTERFACE), 222e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 2234f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 2243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ResolveInfo ri : services) { 2253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ServiceInfo si = ri.serviceInfo; 2263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { 2279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission " 2283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + android.Manifest.permission.BIND_TV_INPUT); 2293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo continue; 2303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 231e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee try { 2324f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.clear(); 233187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ComponentName service = new ComponentName(si.packageName, si.name); 234187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (hasHardwarePermission(pm, service)) { 235187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(service); 236187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState == null) { 237187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // We see this hardware TV input service for the first time; we need to 238187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // prepare the ServiceState object so that we can connect to the service and 239187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // let it add TvInputInfo objects to mInputList if there's any. 240187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(service, userId); 241187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(service, serviceState); 242187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.addAll(serviceState.mInputList); 244187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 245187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2464f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); 247187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 248187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2494f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (TvInputInfo info : inputList) { 250187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (DEBUG) Slog.d(TAG, "add " + info.getId()); 2518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim TvInputState state = userState.inputMap.get(info.getId()); 252187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (state == null) { 253187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state = new TvInputState(); 254187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 255187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state.mInfo = info; 2568e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim inputMap.put(info.getId(), state); 257969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 258226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 259226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Reconnect the service if existing input is updated. 260187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(service, userId); 261187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 262187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.packageSet.add(si.packageName); 263e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } catch (IOException | XmlPullParserException e) { 264e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee Slog.e(TAG, "Can't load TV input " + si.name, e); 265e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 2663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2678e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2688e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : inputMap.keySet()) { 2698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!userState.inputMap.containsKey(inputId)) { 2708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputAddedLocked(userState, inputId); 2718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : userState.inputMap.keySet()) { 2758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!inputMap.containsKey(inputId)) { 2768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputRemovedLocked(userState, inputId); 2778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2798e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2808e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap.clear(); 2818e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap = inputMap; 2823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 2853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 2863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 2873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 2883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 2903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 2913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 2923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 2943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 2953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState = new UserState(); 2963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 2983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 2993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 304b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 305b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 306b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 307b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 3083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 310d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 3113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 312d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 3133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 3153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 3193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 3213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 322d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 3233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 324d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 3253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3269a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 3273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 32972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.clear(); 330d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 3313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 3333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 33472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 33572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 3363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 3373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 348187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private ServiceState getServiceStateLocked(ComponentName name, int userId) { 3493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 350187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(name); 3513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 352187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim throw new IllegalStateException("Service state not found for " + name + " (userId=" 3537de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 365d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3692b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3702b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 374d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("Session not yet created for token " + sessionToken); 3773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 3793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 3823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 3833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 3843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 3853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 387187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean shouldMaintainConnection(ServiceState serviceState) { 388187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return !serviceState.mClientTokens.isEmpty() 389187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || !serviceState.mSessionTokens.isEmpty() 390187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || serviceState.mIsHardware; 391187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // TODO: Find a way to maintain connection only when necessary. 392187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 393187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 394187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private void updateServiceConnectionLocked(ComponentName service, int userId) { 3953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 396187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(service); 3973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 3983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting) { 4012b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!serviceState.mSessionTokens.isEmpty()) { 4022b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // wait until all the sessions are removed. 4032b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 4042b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 4052b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = false; 4062b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 407187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean maintainConnection = shouldMaintainConnection(serviceState); 408187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mService == null && maintainConnection && userId == mCurrentUserId) { 4093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is not yet connected but its state indicates that we 4103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // have pending requests. Then, connect the service. 411d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mBound) { 4123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // We have already bound to the service so we don't try to bind again until after we 4133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // unbind later on. 4143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 417187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "bindServiceAsUser(service=" + service + ", userId=" + userId + ")"); 4183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 419d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim 420187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(service); 421226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Binding service may fail if the service is updating. 422226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // In that case, the connection will be revived in buildTvInputListLocked called by 423226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // onSomePackagesChanged. 424e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee serviceState.mBound = mContext.bindServiceAsUser( 425e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); 426187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (serviceState.mService != null && !maintainConnection) { 4273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is already connected but its state indicates that we have 4283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // nothing to do with it. Then, disconnect the service. 4293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 430187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "unbindService(service=" + service + ")"); 4313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 432d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 433187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.remove(service); 4343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 43772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 43872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 43972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 44072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 44172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 44272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 44372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 44472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 44572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 44672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 44772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 44872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4507de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 45172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 45272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 454187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")"); 4553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4566a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4576a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4586a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 4623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSessionCreated(ITvInputSession session) { 4633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 464187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")"); 4653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 467d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 468fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 469fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 470187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 471187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 472fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 4732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 4742b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 4752b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 4762b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 4772b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 47872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 47972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 48072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 48172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 48272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 48372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 48472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 48572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 486187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 487187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), sessionToken, channels[0], 488187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mSeq); 489fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 4906a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 4913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 493832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 494832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 4951f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 496a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 497a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 4981f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 499a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 500a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 501a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 502a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 503a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5041f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 5051f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 5061f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 5071f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 5081f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 509a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5101f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 511a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 512a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 513a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 514a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 515a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 5161f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onTrackInfoChanged(List<TvTrackInfo> tracks) { 517a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 518a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onTrackInfoChanged(" + tracks + ")"); 520a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 521a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 522a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 523a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 524a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onTrackInfoChanged(tracks, 526a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang sessionState.mSeq); 527a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onTrackInfoChanged"); 529b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 530b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 531b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 532b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 533b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 5349b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 5359b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5369b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5379b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 5389b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5399b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5409b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5419b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5429b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5439b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 5449b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5459b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5469b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5479b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5489b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5499b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5509b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 5519b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 5529b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5539b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5549b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 5559b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5569b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5579b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5589b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5599b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5609b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 5619b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5629b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 5639b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5649b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5659b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5669b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5679b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 568bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed() { 569bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo synchronized (mLock) { 570bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 571bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.d(TAG, "onContentAllowed()"); 572bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 573bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 574bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo return; 575bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 576bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo try { 577bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo sessionState.mClient.onContentAllowed(sessionState.mSeq); 578bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } catch (RemoteException e) { 579bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.e(TAG, "error in onContentAllowed"); 580bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 581bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 582bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 583bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 584bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 5856057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String rating) { 5866057102dbb746593a7d59cf377c969b62e38c664Jae Seo synchronized (mLock) { 5876057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (DEBUG) { 5886057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.d(TAG, "onContentBlocked()"); 5896057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 5906057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 5916057102dbb746593a7d59cf377c969b62e38c664Jae Seo return; 5926057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 5936057102dbb746593a7d59cf377c969b62e38c664Jae Seo try { 5946057102dbb746593a7d59cf377c969b62e38c664Jae Seo sessionState.mClient.onContentBlocked(rating, sessionState.mSeq); 5956057102dbb746593a7d59cf377c969b62e38c664Jae Seo } catch (RemoteException e) { 5966057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.e(TAG, "error in onContentBlocked"); 5976057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 5986057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 5996057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6006057102dbb746593a7d59cf377c969b62e38c664Jae Seo 6016057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 602832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 603832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 604832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 605832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 606832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 607832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 608832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 609832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 610832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 611832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 612832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 613832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 614832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 615832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 616832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 617832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 6183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 6193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 6213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 622187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim service.createSession(channels[1], callback, sessionState.mInfo.getId()); 6233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 6249a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 625fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 626187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null, 627187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim null, sessionState.mSeq); 6283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6296a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 6303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 632d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 6335c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 6343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 635d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 6363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 6379a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 6383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6392b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6412b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 6422b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 6432b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 6442b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 6452b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 6462b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 6472b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 6482b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 6503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 6523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 654fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 655fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang // Remove the session state from the global session state map of the current user. 656fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 657fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 658fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 65931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry, if any. 660d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 66131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 662d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 66331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = System.currentTimeMillis(); 66431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget(); 66531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 66631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 66772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 66872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 66972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 67072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 67172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 67272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 67372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 67472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 67572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 67672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 677187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 678187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 679187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 680187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 681187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 682187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 683fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 684187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 685fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 686fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 687969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void unregisterClientInternalLocked(IBinder clientToken, String inputId, 68872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim int userId) { 68972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 69072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 69172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 69272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mInputIds.remove(inputId); 69372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 69472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(clientToken); 69572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 69672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 69772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 698187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 699187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info == null) { 700187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return; 701187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 702187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 70372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (serviceState == null) { 70472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 70572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 70672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 70772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Remove this client from the client list and unregister the callback. 70872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.remove(clientToken); 70972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (!serviceState.mClientTokens.isEmpty()) { 71072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // We have other clients who want to keep the callback. Do this later. 71172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 71272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 71372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (serviceState.mService == null || serviceState.mCallback == null) { 71472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 71572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 71672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 71772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 71872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 71972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "error in unregisterCallback", e); 72072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } finally { 72172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mCallback = null; 722187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), userId); 72372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 72472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 72572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 7268e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7278e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7288e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7298e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7308e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7318e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7328e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7338e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7348e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7358e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7368e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7378e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7388e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7398e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 7408e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7418e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 7428e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7438e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7448e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7458e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 7468e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7478e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 7488e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7498e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7508e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7528e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 753969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 754969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 7558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 756969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 757969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 758969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 759969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 760969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 761969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 762969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 763969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 764969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 765969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 766969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 7672b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 768969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 7692b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 770969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 7712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7742b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 775969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 776969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 777969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 778969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(inputId); 779969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 780969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 781187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 782187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 783969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 784969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 785969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 786969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 7878e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 788969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 789969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 790969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 7913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 7923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 7933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 7943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 7953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 7963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 7973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 7983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 7993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 800969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 801969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 802969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 804969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 809b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 810b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 811b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 812b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 813b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 814b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 815b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 816b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 817b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 818b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 819b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 820b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 821b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 822b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 823b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 824b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 828969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 8293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 8313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 835969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 836969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 8378e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 838969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 8393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 847969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 8483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 8503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 853969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 854969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 8553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 862d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 8633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 8643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 8653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 8663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 8673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 871187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 872187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 8733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 874187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 875187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 8763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8772b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 8782b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 8795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 8802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 8812b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8822b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 8832b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 8842b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 885187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 88672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 8872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 8882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 8892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 8902b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 8912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 892d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 8933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 894d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 895d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 8967de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 8973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 898187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 8993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 9073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 9083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 9093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 9113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 9142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 9153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 9223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 9233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 9243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 9263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 9293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).setSurface( 9313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo surface); 9323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 9339a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 9343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 937f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 938f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 939f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 940f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 9413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 946e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 947e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 948e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 949e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 950e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 951e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 952e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 953e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 954e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 955e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 956e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho .dispatchSurfaceChanged(format, width, height); 957e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 958e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 959e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 960e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 961e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 962e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 963e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 964e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 965e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 966e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 9673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 9683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 9693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 9713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 9743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).setVolume( 9763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo volume); 9773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 9789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 9793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 9873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void tune(IBinder sessionToken, final Uri channelUri, int userId) { 9883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 9893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 9913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 9943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(channelUri); 996008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho if (TvContract.isChannelUriForPassthroughTvInput(channelUri)) { 997008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 998008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 999008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 100031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long currentTime = System.currentTimeMillis(); 100131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = ContentUris.parseId(channelUri); 100231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 100331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry first, if any. 100431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 100531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 1006d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 100731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1008d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 100931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = currentTime; 101031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args) 101131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo .sendToTarget(); 101231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 101331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 101431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Create a log entry and fill it later. 1015187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim String packageName = sessionState.mInfo.getServiceInfo().packageName; 101631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 10175c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 1018f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 101931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo currentTime); 1020f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 1021f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 102231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1023d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mLogUri = mContentResolver.insert( 102431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo TvContract.WatchedPrograms.CONTENT_URI, values); 102531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1026d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 102731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = ContentUris.parseId(channelUri); 102831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = currentTime; 102931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget(); 10303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 10319a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 10323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 10333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 10409a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 10419bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 10429bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1043903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1044903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1045903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1046903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1047903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1048903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1049903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1050903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 10519bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1052903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1053903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1054903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1055903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1056903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1057903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1058903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1059903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1060903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1061903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 10622c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 10632c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 10642c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10652c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 10662c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 10672c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 10682c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 10692c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 10702c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 10712c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 10722c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 10732c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 10742c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 10752c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 10762c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 10772c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 10782c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 10792c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 10802c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 10812c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 10821f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void selectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 10831f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 10841f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10851f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 10861f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 10871f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 10881f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 10891f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 10901f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 10911f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 10921f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 10931f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 10941f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 10951f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 10961f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 10971f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 10981f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 10991f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11001f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 11011f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 11021f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void unselectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 11031f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 11041f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11051f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "unselectTrack"); 11061f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 11071f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 11081f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 11091f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 11101f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).unselectTrack( 11111f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 11121f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 11131f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in unselectTrack", e); 11141f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11151f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11161f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 11171f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 11181f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 11201f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 11211f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1122a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1123a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1124a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1125a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1126a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1127a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1128a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1129a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1130a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1131a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1132a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1133a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1134a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1135a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1136a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1137a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1138a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1139a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1140a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1141a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1142a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 11439a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 11449a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 11459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 11469a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11479a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 11489a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 11499a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 11509a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 11519a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 11529a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 11539a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 11549a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 11559a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 11569a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11579a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11589a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 11599a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 11609a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11619a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 11639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 11649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 11659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 11669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 11689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 11699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 11709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 11719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 11729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 11739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 11749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 11759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 11769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 11799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 11809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 11839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 11849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 11859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 11869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 11889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 11899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 11909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 11919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 11929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 11939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 11949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 11959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 11969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 11989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 11999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 12009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 12019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1202c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1203c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1204c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1205969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1206c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1207c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1208c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1209c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1210c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1211c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1212c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1213c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1214c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1215c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1216c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1217c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1218c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1219c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1220969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1221969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1222969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1223c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1224c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1225c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1226c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1227c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1228c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1229c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1230c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1231c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1232c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1233969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1234c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1235c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1236c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1237c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1238c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1239c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1240c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1241c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1242969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1243c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1244c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1245c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1246c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1247c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1248c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1249c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1250c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1251c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1252c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1253c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1254c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1255c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1256c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1257c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1258e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1259e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 12600f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1261e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1262e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 12630f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1264e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 12650f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 12660f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1267e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1268e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1269e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1270e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1271e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1272e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1273e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1274e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1275e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1276e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1277e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1278e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1279e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1280e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1281e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1282e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1283e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1284e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1285969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1286e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 12878e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 12888e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1289e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1290e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1291e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1292969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1293e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1294969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1295e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1296e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1297e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1298e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1299e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1300e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1301e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1302e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1303e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1304e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1305e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1306e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1307e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1308e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mInputIds:"); 1309e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1310e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (String inputId : client.mInputIds) { 1311e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(inputId); 1312e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1313e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1314e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1315e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1316e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1317e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1318e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1319e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1320e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1321e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1322e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1323e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1324e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1325e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1326e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1327e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1328e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1329187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1330e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1331187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1332e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1333e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1334e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1335e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1336e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1337e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1338e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens:"); 1339e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1340e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mClientTokens) { 1341e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1342e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1343e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1344e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1345e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1346e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1347e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1348e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1349e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1350e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1351e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1352e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1353e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1354e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1355e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1356e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1357e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1358e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1359e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1360e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1361e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1362e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1363e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1364e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1365e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1366e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1367e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1368e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1369187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1370e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1371e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1372e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1373e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1374e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1375e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1376e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1377e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1378e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1379e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1380e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1381969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1382969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1383969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1384969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1385969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1386969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1387969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1388e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1389e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1390e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1391e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 13923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1394969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1395969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1396969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1397969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1398969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1399969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1400969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1401969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1402969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1403969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1404969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1405969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1406969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 14073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1408969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1409969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 14103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1411969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1412969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 14135c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 141472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 141572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 141672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 141772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 14183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1419187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1420187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 14213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 14223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 14233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 14243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1425969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1426969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1427969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1428969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 14293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 143172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 143272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<String> mInputIds = new ArrayList<String>(); 143372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 143472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 143572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 143672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 143772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 143872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 143972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 144072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 144172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 144272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 144372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 144472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return mInputIds.isEmpty() && mSessionTokens.isEmpty(); 144572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 144672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 144772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 144872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 144972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 145072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 145172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1452969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // removed in releaseSessionLocked() or unregisterClientInternalLocked(). 145372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 145472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 145572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 145672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 145772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 145872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 145972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mInputIds.size() > 0) { 1460969167dc05a6485a32d160895871cff46fd81884Wonsik Kim unregisterClientInternalLocked( 146172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken, clientState.mInputIds.get(0), mUserId); 146272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 146372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 146472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 146572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 146672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 146772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 146872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 14693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 147072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); 1471d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1472d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 1473187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final ComponentName mName; 1474187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final boolean mIsHardware; 1475187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>(); 14763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1477d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1478d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1479d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 14802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 14813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1482187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private ServiceState(ComponentName name, int userId) { 1483187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mName = name; 1484187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mConnection = new InputServiceConnection(name, userId); 1485187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mName); 14863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 14892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1490187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final TvInputInfo mInfo; 1491d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1492d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1493d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 14942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 149572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1496d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1497d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 14983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1499187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client, int seq, 15002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim int callingUid, int userId) { 150172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 1502187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mInfo = info; 15032b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 15042b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 15052b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 15062b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 15072b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 15082b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 15092b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 15102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 15112b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 15122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 15132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 15142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 15152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 15162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 15172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 15182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 15192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 152072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 15212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 15223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 15253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 1526187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final ComponentName mName; 15273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 15283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1529187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private InputServiceConnection(ComponentName name, int userId) { 1530187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mName = name; 15313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 15323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 15343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 15353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onServiceConnected(ComponentName name, IBinder service) { 15363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 1537187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onServiceConnected(name=" + name + ")"); 15383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1540969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 1541187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(mName); 1542d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 15433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 15443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1545187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 1546187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mCallback = new ServiceCallback(mName, mUserId); 15473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1548d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 15493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 15509a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 15513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 15543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1555d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1556d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 15573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1558969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1559187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 1560187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (inputState.mInfo.getComponent().equals(name) 1561187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 15628e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1563187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1564187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1565187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1566187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1567187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 15684f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 15694f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1570187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1571187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1572187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1573187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1574187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1575187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1576187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1577187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 15784f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<HdmiCecDeviceInfo> cecDeviceInfoList = 15794f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHdmiCecInputDeviceList(); 15804f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (HdmiCecDeviceInfo cecDeviceInfo : cecDeviceInfoList) { 15814f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 15824f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 15834f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 15844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 15854f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 15864f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1587969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 15883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 15903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 15913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 15923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onServiceDisconnected(ComponentName name) { 15933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 1594187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onServiceDisconnected(name=" + name + ")"); 15953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1596187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!mName.equals(name)) { 15972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 1598187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim + mName + " (expected), " + name + " (actual)."); 15992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 16012b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 1602187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(mName); 16032b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 16042b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 16052b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 16062b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 16072b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 16082b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 16092b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 16102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 16112b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 16122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 16132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 16142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 1615187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 16162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1619187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 1620187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (inputState.mInfo.getComponent().equals(name)) { 16218e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1622187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 1623187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1624187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1625187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(mName, mUserId); 16262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 16283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 1632187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final ComponentName mName; 16333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 16343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1635187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceCallback(ComponentName name, int userId) { 1636187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mName = name; 16373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 16383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 16404f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 16414f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 16424f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 16434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 16444f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 16454f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 16464f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 16474f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 16484f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (inputInfo.getId() == null || !mName.equals(inputInfo.getComponent())) { 16494f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 16504f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 16514f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 16524f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 16534f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 16544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ServiceState serviceState = getServiceStateLocked(mName, mUserId); 16554f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 16564f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 16574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 16584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 16593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 16604f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 16614f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 16624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 1663187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 16644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 16654f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 16664f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 16674f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1668187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 16694f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 16704f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHdmiCecTvInput(int logicalAddress, TvInputInfo inputInfo) { 16714f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 16724f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 16734f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 16744f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHdmiCecTvInput(logicalAddress, inputInfo); 16754f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 16763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1677187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1678187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1679187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1680187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 16814f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 16823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1683187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = getServiceStateLocked(mName, mUserId); 1684187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 1685187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 1686187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 1687187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 1688187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 1689187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 1690187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 1691187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1692187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1693187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 1694187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 16954f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 1696187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 1697187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 1698187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 16993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 170231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 170331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final class LogHandler extends Handler { 170431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_OPEN_ENTRY = 1; 170531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_UPDATE_ENTRY = 2; 170631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_CLOSE_ENTRY = 3; 170731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 170831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public LogHandler(Looper looper) { 170931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 171031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 171131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 171231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 171331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 171431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 171531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_OPEN_ENTRY: { 171631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 171731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 171831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 171931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 172031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 172131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 172231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 172331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 172431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_UPDATE_ENTRY: { 172531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 172631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 172731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 172831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 172931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onUpdateEntry(uri, channelId, time); 173031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 173131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 173231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 173331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_CLOSE_ENTRY: { 173431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 173531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 173631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg2; 173731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onCloseEntry(uri, time); 173831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 173931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 174031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 174131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 17426a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 174331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 174431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 174531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 174631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 174731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 174831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onOpenEntry(Uri uri, long channelId, long watchStarttime) { 174931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 1750f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_TITLE, 1751f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, 1752f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, 1753bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcbJae Seo TvContract.Programs.COLUMN_SHORT_DESCRIPTION 175431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 1755f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " 1756f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND " 1757f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + ">?"; 175831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] selectionArgs = { 175931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(channelId), 176031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime), 176131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime) 176231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 1763f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String sortOrder = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + " ASC"; 176431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 176531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 176631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection, 176731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo selection, selectionArgs, sortOrder); 176831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 176931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1770f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, cursor.getString(0)); 1771f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 1772f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo cursor.getLong(1)); 177331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(2); 1774f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 1775f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3)); 177631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 177731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 177831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Schedule an update when the current program ends. 177931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 178031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg1 = uri; 178131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = channelId; 178231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = endTime; 178331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args); 178431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo sendMessageDelayed(msg, endTime - System.currentTimeMillis()); 178531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 178631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 178731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 178831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 178931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 179031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 179131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 179231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 179331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onUpdateEntry(Uri uri, long channelId, long time) { 179431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 1795f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 1796f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 1797f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_TITLE, 1798f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 1799f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, 1800f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_DESCRIPTION 180131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 180231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 180331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 180431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(uri, projection, null, null, null); 180531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 180631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchStartTime = cursor.getLong(0); 180731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchEndTime = cursor.getLong(1); 180831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String title = cursor.getString(2); 180931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long startTime = cursor.getLong(3); 181031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(4); 181131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String description = cursor.getString(5); 181231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 181331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Do nothing if the current log entry is already closed. 181431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (watchEndTime > 0) { 181531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 181631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 181731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 181831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // The current program has just ended. Create a (complete) log entry off the 181931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // current entry. 182031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1821f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 182231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo watchStartTime); 1823f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, time); 1824f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 1825f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, title); 1826f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, startTime); 1827f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 1828f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, description); 182931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 183031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 183131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 183231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 183331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 183431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 183531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 183631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Re-open the current log entry with the next program information. 183731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 183831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 183931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 184031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onCloseEntry(Uri uri, long watchEndTime) { 184131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1842f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime); 184331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 184431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 184531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 1846969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1847187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 1848187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1849187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 1850969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 1851969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 1852969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1853969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1854187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1855187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1856187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 1857187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 1858187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 1859187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 1860187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 1861187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 1862187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1863187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 1864187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1865187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1866187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1867187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1868187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1869187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1870187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1871187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 18724f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 1873187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 1874187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 1875187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 1876187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 1877187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 1878187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 18794f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 1880187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1881187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 1882187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1883187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1884187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1885187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1886187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1887187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 18884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDeviceInfo) { 1889187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 18904f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 18914f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 18924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 18934f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 18944f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 18954f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 18964f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 18974f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 18984f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 18994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1900187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1901187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1902187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1903187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 19044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDeviceInfo) { 1905187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 19064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 19074f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 19084f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 19094f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 19104f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 19114f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceRemoved(cecDeviceInfo); 19124f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 19134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceRemoved", e); 19144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19154f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1916187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1917187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1918969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 19193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 1920