TvInputManagerService.java revision 8d4ded0058de5c573ccf79c4596bf5eb1b14fad3
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; 4061f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jangimport android.hardware.hdmi.HdmiDeviceInfo; 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; 50783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seoimport android.media.tv.TvContentRating; 51d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvContract; 52d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputHardwareInfo; 53d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputInfo; 54d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputService; 55c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heoimport android.media.tv.TvStreamConfig; 561f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport android.media.tv.TvTrackInfo; 573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.net.Uri; 583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Binder; 59832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 6031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Handler; 613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.IBinder; 6231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Looper; 6331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Message; 643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Process; 653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.RemoteException; 663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.UserHandle; 679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Slog; 683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.util.SparseArray; 696a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputChannel; 703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.view.Surface; 713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.internal.content.PackageMonitor; 7331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.internal.os.SomeArgs; 74e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport com.android.internal.util.IndentingPrintWriter; 7531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.server.IoThread; 763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.server.SystemService; 773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 78e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport org.xmlpull.v1.XmlPullParserException; 79e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee 80e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.FileDescriptor; 81e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport java.io.IOException; 82e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.PrintWriter; 833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.ArrayList; 843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.HashMap; 855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.HashSet; 86187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport java.util.Iterator; 873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.List; 883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.Map; 895c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.Set; 903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/** This class provides a system service that manages television inputs. */ 923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopublic final class TvInputManagerService extends SystemService { 933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // STOPSHIP: Turn debugging off. 943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final boolean DEBUG = true; 953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final String TAG = "TvInputManagerService"; 963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Context mContext; 98c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareManager mTvInputHardwareManager; 993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final ContentResolver mContentResolver; 10131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A global lock. 1033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Object mLock = new Object(); 1043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // ID of the current user. 1063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int mCurrentUserId = UserHandle.USER_OWNER; 1073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A map from user id to UserState. 1093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 1103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final Handler mLogHandler; 11231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 11831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler = new LogHandler(IoThread.get().getLooper()); 11931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 120187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); 12131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 123783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo mUserStates.put(mCurrentUserId, new UserState(mContext, mCurrentUserId)); 1243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onStart() { 1293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo publishBinderService(Context.TV_INPUT_SERVICE, new BinderService()); 1303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1320ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee @Override 1330ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee public void onBootPhase(int phase) { 1340ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1350ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee registerBroadcastReceivers(); 136187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 1370ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee synchronized (mLock) { 1380ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee buildTvInputListLocked(mCurrentUserId); 1390ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1400ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 141969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.onBootPhase(phase); 1420ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1430ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee 1443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void registerBroadcastReceivers() { 1453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageMonitor monitor = new PackageMonitor() { 1463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSomePackagesChanged() { 1483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(mCurrentUserId); 1503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1525c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1535c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo @Override 1545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo public void onPackageRemoved(String packageName, int uid) { 1555c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo synchronized (mLock) { 1565c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo UserState userState = getUserStateLocked(mCurrentUserId); 157969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (!userState.packageSet.contains(packageName)) { 1585c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo // Not a TV input package. 1595c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo return; 1605c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1615c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1625c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1635c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ArrayList<ContentProviderOperation> operations = 1645c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo new ArrayList<ContentProviderOperation>(); 1655c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1665c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; 1675c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String[] selectionArgs = { packageName }; 1685c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1695c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI) 1705c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1715c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI) 1725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1735c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation 1745c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .newDelete(TvContract.WatchedPrograms.CONTENT_URI) 1755c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1765c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ContentProviderResult[] results = null; 1785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo try { 1795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations); 1805c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } catch (RemoteException | OperationApplicationException e) { 1815c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.e(TAG, "error in applyBatch" + e); 1825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo if (DEBUG) { 1855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid 1865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo + ")"); 1875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "results=" + results); 1885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1895c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 1913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo monitor.register(mContext, null, UserHandle.ALL, true); 1923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo IntentFilter intentFilter = new IntentFilter(); 1943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 1953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext.registerReceiverAsUser(new BroadcastReceiver() { 1973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onReceive(Context context, Intent intent) { 1993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String action = intent.getAction(); 2003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (Intent.ACTION_USER_SWITCHED.equals(action)) { 2013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 2033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }, UserHandle.ALL, intentFilter, null, null); 2073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2099e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private static boolean hasHardwarePermission(PackageManager pm, ComponentName component) { 210187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, 2119e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee component.getPackageName()) == PackageManager.PERMISSION_GRANTED; 212187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 213187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void buildTvInputListLocked(int userId) { 2153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 216969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2178e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 218969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.packageSet.clear(); 2193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (DEBUG) Slog.d(TAG, "buildTvInputList"); 2213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageManager pm = mContext.getPackageManager(); 2223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo List<ResolveInfo> services = pm.queryIntentServices( 223e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee new Intent(TvInputService.SERVICE_INTERFACE), 224e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 2254f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 2263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ResolveInfo ri : services) { 2273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ServiceInfo si = ri.serviceInfo; 2283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { 2299a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission " 2303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + android.Manifest.permission.BIND_TV_INPUT); 2313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo continue; 2323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 233e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee try { 2344f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.clear(); 2359e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ComponentName component = new ComponentName(si.packageName, si.name); 2369e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (hasHardwarePermission(pm, component)) { 2379e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 238187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState == null) { 239187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // We see this hardware TV input service for the first time; we need to 240187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // prepare the ServiceState object so that we can connect to the service and 241187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // let it add TvInputInfo objects to mInputList if there's any. 2429e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState = new ServiceState(component, userId); 2439e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee userState.serviceStateMap.put(component, serviceState); 244187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2454f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.addAll(serviceState.mInputList); 246187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 247187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2484f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); 249187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 250187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2514f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (TvInputInfo info : inputList) { 252187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (DEBUG) Slog.d(TAG, "add " + info.getId()); 2538e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim TvInputState state = userState.inputMap.get(info.getId()); 254187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (state == null) { 255187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state = new TvInputState(); 256187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 257187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state.mInfo = info; 2588e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim inputMap.put(info.getId(), state); 259969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 260226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 261226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Reconnect the service if existing input is updated. 2629e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(component, userId); 263187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 264187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.packageSet.add(si.packageName); 265e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } catch (IOException | XmlPullParserException e) { 266e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee Slog.e(TAG, "Can't load TV input " + si.name, e); 267e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 2683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : inputMap.keySet()) { 2718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!userState.inputMap.containsKey(inputId)) { 2728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputAddedLocked(userState, inputId); 2738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : userState.inputMap.keySet()) { 2778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!inputMap.containsKey(inputId)) { 2788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputRemovedLocked(userState, inputId); 2798e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2808e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2818e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2828e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap.clear(); 2838e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap = inputMap; 2845c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 2855c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.clear(); 2865c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(TvContentRating.SYSTEM_CONTENT_RATING_SYSTEM_XML); 2875c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim for (TvInputState state : userState.inputMap.values()) { 2885c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri(); 2895c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim if (ratingSystemXmlUri != null) { 2905c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // TODO: need to check the validation of xml format and the duplication of rating 2915c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // systems. 2925c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(state.mInfo.getRatingSystemXmlUri()); 2935c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2945c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 2983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 2993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 3043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 3053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 308783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState = new UserState(mContext, userId); 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 3113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 3123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 317b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 318b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 319b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 320b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 3213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 3223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 323d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 3243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 325d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 3263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 3283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 3323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 3343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 335d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 3363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 337d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 3383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 3403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 34272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.clear(); 343d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 3443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 3463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 34772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 34872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 3493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 3503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3619e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState getServiceStateLocked(ComponentName component, int userId) { 3623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3639e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 3643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 3659e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee throw new IllegalStateException("Service state not found for " + component + " (userId=" 3667de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 378d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3822b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3832b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3842b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3864c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return getSessionLocked(getSessionStateLocked(sessionToken, callingUid, userId)); 3874c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 3884c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 3894c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private ITvInputSession getSessionLocked(SessionState sessionState) { 390d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3924c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee throw new IllegalStateException("Session not yet created for token " 3934c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee + sessionState.mSessionToken); 3943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 3963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 3993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 4003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 4013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 4023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 404187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean shouldMaintainConnection(ServiceState serviceState) { 405187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return !serviceState.mClientTokens.isEmpty() 406187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || !serviceState.mSessionTokens.isEmpty() 407187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || serviceState.mIsHardware; 408187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // TODO: Find a way to maintain connection only when necessary. 409187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 410187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 4119e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private void updateServiceConnectionLocked(ComponentName component, int userId) { 4123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 4139e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 4143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 4153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting) { 4182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!serviceState.mSessionTokens.isEmpty()) { 4192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // wait until all the sessions are removed. 4202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 4212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 4222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = false; 4232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 424187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean maintainConnection = shouldMaintainConnection(serviceState); 425187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mService == null && maintainConnection && userId == mCurrentUserId) { 4263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is not yet connected but its state indicates that we 4273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // have pending requests. Then, connect the service. 428d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mBound) { 4293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // We have already bound to the service so we don't try to bind again until after we 4303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // unbind later on. 4313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4349e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "bindServiceAsUser(service=" + component + ", userId=" + userId + ")"); 4353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 436d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim 4379e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component); 438226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Binding service may fail if the service is updating. 439226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // In that case, the connection will be revived in buildTvInputListLocked called by 440226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // onSomePackagesChanged. 441e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee serviceState.mBound = mContext.bindServiceAsUser( 442e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); 443187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (serviceState.mService != null && !maintainConnection) { 4443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is already connected but its state indicates that we have 4453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // nothing to do with it. Then, disconnect the service. 4463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4479e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "unbindService(service=" + component + ")"); 4483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 449d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 4509e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee userState.serviceStateMap.remove(component); 4513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 45472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 45572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 45672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 45772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 45872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 45972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 46072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 46172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 46272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 46372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 46472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 46572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4677de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 46872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 46972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 471187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")"); 4723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4736a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4746a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4756a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 479bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) { 4803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 481187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")"); 4823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 484d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 485bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken = harewareSessionToken; 486fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 487fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 488187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 489187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 490fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 4912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 4922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 4932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 4942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 4952b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 49672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 49772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 49872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 49972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 50072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 50172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 50272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 50372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 504187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 505187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), sessionToken, channels[0], 506187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mSeq); 507fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 5086a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 5093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 511832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 512832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 5131f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 514a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 515a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5161f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 517a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 518a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 519a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 520a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 521a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5221f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 5231f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 5241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 5251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 5261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 527a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 529a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 530a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 531a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 532a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 533a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 53410d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTracksChanged(List<TvTrackInfo> tracks) { 535a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 536a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 53710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTracksChanged(" + tracks + ")"); 538a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 539a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 540a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 541a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 542a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 54310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTracksChanged(tracks, sessionState.mSeq); 544a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 54510d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTracksChanged"); 546b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 547b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 548b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 549b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 550b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 55110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTrackSelected(int type, String trackId) { 552d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo synchronized (mLock) { 553d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (DEBUG) { 55410d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")"); 555d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 556d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 557d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo return; 558d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 559d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo try { 56010d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTrackSelected(type, trackId, sessionState.mSeq); 561d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } catch (RemoteException e) { 56210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTrackSelected"); 563d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 564d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 565d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 566d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 567d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo @Override 5689b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 5699b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5709b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5719b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 5729b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5739b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5749b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5759b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5769b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5779b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 5789b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5799b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5809b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5819b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5829b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5839b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5849b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 5859b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 5869b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5879b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5889b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 5899b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5909b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5919b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5929b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5939b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5949b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 5959b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5969b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 5979b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5989b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5999b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6009b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 6019b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 602bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed() { 603bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo synchronized (mLock) { 604bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 605bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.d(TAG, "onContentAllowed()"); 606bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 607bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 608bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo return; 609bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 610bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo try { 611bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo sessionState.mClient.onContentAllowed(sessionState.mSeq); 612bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } catch (RemoteException e) { 613bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.e(TAG, "error in onContentAllowed"); 614bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 615bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 616bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 617bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 618bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 6196057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String rating) { 6206057102dbb746593a7d59cf377c969b62e38c664Jae Seo synchronized (mLock) { 6216057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (DEBUG) { 6226057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.d(TAG, "onContentBlocked()"); 6236057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6246057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 6256057102dbb746593a7d59cf377c969b62e38c664Jae Seo return; 6266057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6276057102dbb746593a7d59cf377c969b62e38c664Jae Seo try { 6286057102dbb746593a7d59cf377c969b62e38c664Jae Seo sessionState.mClient.onContentBlocked(rating, sessionState.mSeq); 6296057102dbb746593a7d59cf377c969b62e38c664Jae Seo } catch (RemoteException e) { 6306057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.e(TAG, "error in onContentBlocked"); 6316057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6326057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6336057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6346057102dbb746593a7d59cf377c969b62e38c664Jae Seo 6356057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 636ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho public void onLayoutSurface(int left, int top, int right, int bottom) { 637ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho synchronized (mLock) { 638ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (DEBUG) { 639ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top 640ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho + ", right=" + right + ", bottom=" + bottom + ",)"); 641ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 642ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 643ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho return; 644ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 645ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho try { 646ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mClient.onLayoutSurface(left, top, right, bottom, 647ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mSeq); 648ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } catch (RemoteException e) { 649ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.e(TAG, "error in onLayoutSurface"); 650ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 651ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 652ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 653ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho 654ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho @Override 655832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 656832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 657832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 658832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 659832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 660832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 661832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 662832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 663832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 664832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 665832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 666832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 667832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 668832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 669832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 670832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 6713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 6723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 6743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 675187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim service.createSession(channels[1], callback, sessionState.mInfo.getId()); 6763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 6779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 678fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 679187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null, 680187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim null, sessionState.mSeq); 6813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6826a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 6833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 685d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 6865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 6873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 688d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 6893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 6909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 6913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 6952b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 6962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 6972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 6982b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 6992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 7002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 7012b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7022b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 7033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7042b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 7053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 707fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 708fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 709abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 710abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken = null; 711abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 712abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 713abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee // Remove the session state from the global session state map of the current user. 714fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 715fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 7168d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee if (sessionState == null) { 7178d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee return; 7188d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 7198d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee 72031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry, if any. 721d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 72231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 723d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 72431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = System.currentTimeMillis(); 72531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget(); 72631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 72731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 72872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 72972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 73072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 73172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 73272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 73372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 73472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 73572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 738187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 739187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 740187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 741187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 742187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 743187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 744fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 745187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 746fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 747fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 7488e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7498e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7508e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7528e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7538e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7548e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7568e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7578e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7588e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7598e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7608e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7618e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 7628e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7638e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 7648e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7658e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7668e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7678e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 7688e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 7708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 775969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 776969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 7778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 778969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 779969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 780969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 781969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 782969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 783969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 784969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 785969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 786969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 787969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 788969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 7892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 790969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 7912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 792969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 7932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7952b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 797969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 798969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 799969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 800c88f1916b8ab7f5f75a00375c6fb4873ea5044afJi-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(inputState.mInfo.getComponent()); 801969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 802969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 803187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 804187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 805969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 806969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 807969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 808969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 8098e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 810969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 811969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 812969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 8133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 8143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 8163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 8183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 822969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 823969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 824969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 826969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 831b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 832b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 833b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 834b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 835b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 836b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 837b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 838b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 839b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 840b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 841b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 842b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 843b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 844b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 845b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 846b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8505c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim public List<Uri> getTvContentRatingSystemXmls(int userId) { 8515c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8525c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls"); 8535c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final long identity = Binder.clearCallingIdentity(); 8545c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim try { 8555c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim synchronized (mLock) { 8565c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim UserState userState = getUserStateLocked(resolvedUserId); 8575c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>(); 8585c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet); 8595c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim return ratingSystemXmlUriList; 8605c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8615c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } finally { 8625c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.restoreCallingIdentity(identity); 8635c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8645c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8655c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 8665c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim @Override 867969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 8683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 8703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 874969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 875969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 8768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 877969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 8783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 886969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 8873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 8893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 892969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 893969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 8943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 901783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isParentalControlsEnabled(int userId) { 902783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 903783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isParentalControlsEnabled"); 904783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 905783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 906783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 907783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 908783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isParentalControlsEnabled(); 909783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 910783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 911783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 912783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 913783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 914783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 915783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 916783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void setParentalControlsEnabled(boolean enabled, int userId) { 917783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 918783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 919783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "setParentalControlsEnabled"); 920783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 921783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 922783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 923783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 924783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.setParentalControlsEnabled(enabled); 925783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 926783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 927783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 928783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 929783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 930783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 931783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 932783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isRatingBlocked(String rating, int userId) { 933783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 934783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isRatingBlocked"); 935783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 936783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 937783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 938783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 939783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isRatingBlocked( 940783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 941783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 942783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 943783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 944783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 945783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 946783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 947783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 948783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public List<String> getBlockedRatings(int userId) { 949783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 950783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "getBlockedRatings"); 951783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 952783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 953783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 954783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 955783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo List<String> ratings = new ArrayList<String>(); 956783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo for (TvContentRating rating 957783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo : userState.persistentDataStore.getBlockedRatings()) { 958783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ratings.add(rating.flattenToString()); 959783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 960783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return ratings; 961783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 962783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 963783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 964783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 965783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 966783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 967783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 968783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void addBlockedRating(String rating, int userId) { 969783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 970783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 971783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "addBlockedRating"); 972783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 973783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 974783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 975783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 976783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.addBlockedRating( 977783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 978783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 979783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 980783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 981783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 982783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 983783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 984783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 985783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void removeBlockedRating(String rating, int userId) { 986783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 987783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 988783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "removeBlockedRating"); 989783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 990783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 991783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 992783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 993783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.removeBlockedRating( 994783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 995783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 996783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 997783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 998783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 999783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1000783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1001783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private void ensureParentalControlsPermission() { 1002783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo if (mContext.checkCallingPermission( 1003783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) 1004783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo != PackageManager.PERMISSION_GRANTED) { 1005783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo throw new SecurityException( 1006783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo "The caller does not have parental controls permission"); 1007783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1008783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1009783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1010783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1011d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 10123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 10133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 10163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 1020187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 1021187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 10223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 1023187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 1024187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 10253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 10272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 10285c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 10292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 10302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 10312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 10332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 1034187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 103572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 10362b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10372b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 10382b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 10392b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10402b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 1041d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 10423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1043d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 1044d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 10457de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 10463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 1047187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 10483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 10573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 10603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10632b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 10643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10714c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void setMainSession(IBinder sessionToken, int userId) { 10724c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int callingUid = Binder.getCallingUid(); 10734c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10744c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userId, "setMainSession"); 10754c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final long identity = Binder.clearCallingIdentity(); 10764c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 10774c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (mLock) { 1078982abe693f66037ca265b88057eceb5a3e815182Ji-Hwan Lee UserState userState = getUserStateLocked(resolvedUserId); 1079956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (userState.mainSessionToken == sessionToken) { 10804c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return; 10814c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10824c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1083956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee SessionState newMainSessionState = getSessionStateLocked( 1084956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee sessionToken, callingUid, resolvedUserId); 1085956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (newMainSessionState.mHardwareSessionToken != null) { 1086956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState = getSessionStateLocked( 1087956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState.mHardwareSessionToken, 1088956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee Process.SYSTEM_UID, resolvedUserId); 1089956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee } 1090956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ServiceState newMainServiceState = getServiceStateLocked( 1091956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState.mInfo.getComponent(), resolvedUserId); 1092956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ITvInputSession newMainSession = getSessionLocked(newMainSessionState); 10934c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1094956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ServiceState oldMainServiceState = null; 1095956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ITvInputSession oldMainSession = null; 1096abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (userState.mainSessionToken != null) { 1097956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee SessionState oldMainSessionState = getSessionStateLocked( 1098abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId); 1099956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (oldMainSessionState.mHardwareSessionToken != null) { 1100956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState = getSessionStateLocked( 1101956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState.mHardwareSessionToken, 1102956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee Process.SYSTEM_UID, resolvedUserId); 1103956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee } 1104956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainServiceState = getServiceStateLocked( 1105956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState.mInfo.getComponent(), resolvedUserId); 1106956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSession = getSessionLocked(oldMainSessionState); 1107abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 1108abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 11094c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userState.mainSessionToken = sessionToken; 11104c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1111956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // Inform the new main session first. 1112956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // See {@link TvInputService#onSetMainSession}. 1113956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (newMainServiceState.mIsHardware) { 11144c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 1115956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSession.setMainSession(true); 11164c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 11174c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 11184c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11194c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 1120956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (oldMainSession != null && oldMainServiceState.mIsHardware) { 11214c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 1122956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSession.setMainSession(false); 11234c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 11244c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 11254c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11264c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11274c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11284c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } finally { 11294c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Binder.restoreCallingIdentity(identity); 11304c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11314c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11324c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 11334c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 11343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 11353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 11383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1142bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1143bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1144bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken == null) { 1145bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setSurface(surface); 1146bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } else { 1147bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1148bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setSurface(surface); 1149bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 11503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 11519a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 11523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 1155f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 1156f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 1157f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 1158f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 11593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1164e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 1165e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 1166e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 1167e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1168e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 1169e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 1170e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1171e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 1172e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1173bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1174bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1175bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).dispatchSurfaceChanged(format, width, height); 1176bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1177bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, Process.SYSTEM_UID, 1178bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId).dispatchSurfaceChanged(format, width, height); 1179bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1180e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 1181e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 1182e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1183e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1184e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 1185e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 1186e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1187e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1188e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 1189e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 11903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 1191bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_ON = 1.0f; 1192bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_OFF = 0f; 11933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 11963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1200bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1201bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1202bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setVolume(volume); 1203bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1204bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Here, we let the hardware session know only whether volume is on or 1205bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // off to prevent that the volume is controlled in the both side. 1206bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1207bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f) 1208bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF); 1209bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 12103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 12123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 12193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 12201a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) { 12213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 12223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 12243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 12253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 12273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12281a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( 12291a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim channelUri, params); 1230008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho if (TvContract.isChannelUriForPassthroughTvInput(channelUri)) { 1231008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 1232008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 1233008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 123431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long currentTime = System.currentTimeMillis(); 123531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = ContentUris.parseId(channelUri); 123631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 123731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry first, if any. 123831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 123931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 1240d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 124131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1242d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 124331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = currentTime; 124431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args) 124531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo .sendToTarget(); 124631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 124731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 124831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Create a log entry and fill it later. 1249187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim String packageName = sessionState.mInfo.getServiceInfo().packageName; 125031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 12515c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 1252f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 125331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo currentTime); 1254f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 1255f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 12561a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (params != null) { 12571a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim values.put(TvContract.WatchedPrograms.COLUMN_TUNE_PARAMS, 12581a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim encodeTuneParams(params)); 12591a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 126031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1261d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mLogUri = mContentResolver.insert( 126231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo TvContract.WatchedPrograms.CONTENT_URI, values); 126331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1264d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 126531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = ContentUris.parseId(channelUri); 126631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = currentTime; 1267579befecb248162021929ab58ffd23f1724cc6beJae Seo args.arg4 = sessionState; 126831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget(); 12693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 12713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 12723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12809bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 12819bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1282903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1283903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1284903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1285903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1286903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1287903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1288903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1289903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 12909bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1291903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1292903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1293903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1294903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1295903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1296903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1297903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1298903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1299903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1300903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 13012c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 13022c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 13032c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13042c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 13052c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 13062c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13072c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 13082c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13092c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 13102c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 13112c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 13122c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 13132c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13142c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13152c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 13162c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 13172c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13182c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13192c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 13202c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 132110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void selectTrack(IBinder sessionToken, int type, String trackId, int userId) { 13221f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 13231f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 13251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 13261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13271f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 13281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13291f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 133010d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo type, trackId); 13311f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 13321f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 13331f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13341f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13351f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 13361f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 13371f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13381f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13391f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 13401f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1341a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1342a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1343a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1344a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1345a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1346a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1347a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1348a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1349a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1350a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1351a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1352a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1353a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1354a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1355a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1356a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1357a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1358a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1359a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1360a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1361a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 13629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 13639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 13649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 13679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 13739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 13759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 13849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 13879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 13939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 13959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 14029a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 14039a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 14049a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 14059a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 14069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 14079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 14089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 14109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 14129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 14139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 14149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 14159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14179a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 14189a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 14199a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1421c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1422c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1423c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1424969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1425c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1426c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1427c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1428c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1429c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1430c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1431c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1432c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1433c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1434c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1435c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1436c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1437c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1438c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1439969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1440969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1441969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1442c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1443c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1444c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1445c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1446c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1447c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1448c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1449c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1450c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1451c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1452969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1453c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1454c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1455c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1456c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1457c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1458c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1459c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1460c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1461969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1462c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1463c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1464c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1465c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1466c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1467c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1468c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1469c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1470c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1471c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1472c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1473c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1474c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1475c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1476c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1477e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1478e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 1479c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) 1480c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1481c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1482c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1483c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1484c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1485c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1486c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1487c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1488c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1489c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1490c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "getAvailableTvStreamConfigList"); 1491c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1492c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.getAvailableTvStreamConfigList( 1493c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo inputId, callingUid, resolvedUserId); 1494c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1495c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1496c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1497c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1498c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1499c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1500c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config, 1501c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int userId) 1502c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1503c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1504c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1505c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1506c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1507c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1508c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1509c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1510c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1511c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1512c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "captureFrame"); 1513c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1514bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang String hardwareInputId = null; 151579124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 151679124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1517bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (userState.inputMap.get(inputId) == null) { 1518bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "Input not found for " + inputId); 1519bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang return false; 1520bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1521bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1522bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mInfo.getId().equals(inputId) 1523bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang && sessionState.mHardwareSessionToken != null) { 1524bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang hardwareInputId = userState.sessionStateMap.get( 1525bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken).mInfo.getId(); 1526bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang break; 1527bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1528bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 152979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 1530c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.captureFrame( 1531bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang (hardwareInputId != null) ? hardwareInputId : inputId, 153279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo surface, config, callingUid, resolvedUserId); 1533c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1534c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1535c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1536c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1537c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1538c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1539df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo public boolean isSingleSessionActive(int userId) throws RemoteException { 1540df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final long identity = Binder.clearCallingIdentity(); 1541df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int callingUid = Binder.getCallingUid(); 1542df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1543df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo userId, "isSingleSessionActive"); 1544df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo try { 1545df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo synchronized (mLock) { 1546df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1547df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (userState.sessionStateMap.size() == 1) { 1548df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1549df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1550df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo else if (userState.sessionStateMap.size() == 2) { 1551df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo SessionState[] sessionStates = userState.sessionStateMap.values().toArray( 1552df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo new SessionState[0]); 1553df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo // Check if there is a wrapper input. 1554df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (sessionStates[0].mHardwareSessionToken != null 1555df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo || sessionStates[1].mHardwareSessionToken != null) { 1556df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1557df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1558df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1559df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return false; 1560df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1561df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } finally { 1562df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo Binder.restoreCallingIdentity(identity); 1563df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1564df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1565df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo 1566df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo @Override 15670f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1568e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1569e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 15700f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1571e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 15720f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 15730f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1574e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1575e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1576e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1577e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1578e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1579e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1580e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1581e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1582e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1583e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1584e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1585e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1586e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1587e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1588e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1589e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1590e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1591e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1592969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1593e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 15948e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 15958e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1596e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1597e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1598e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1599969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1600e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1601969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1602e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1603e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1604e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1605e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1606e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1607e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1608e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1609e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1610e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1611e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1612e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1613e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1614e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1615e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1616e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1617e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1618e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1619e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1620e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1621e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1622e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1623e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1624e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1625e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1626e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1627e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1628e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1629187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1630e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1631187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1632e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1633e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1634e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1635e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1636e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1637e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1638e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens:"); 1639e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1640e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mClientTokens) { 1641e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1642e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1643e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1644e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1645e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1646e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1647e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1648e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1649e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1650e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1651e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1652e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1653e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1654e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1655e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1656e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1657e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1658e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1659e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1660e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1661e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1662e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1663e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1664e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1665e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1666e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1667e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1668e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1669187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1670e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1671e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1672e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1673e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1674e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1675e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1676e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1677bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang pw.println("mHardwareSessionToken: " + session.mHardwareSessionToken); 1678e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1679e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1680e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1681e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1682969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1683969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1684969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1685969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1686969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1687969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1688969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1689956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee pw.println("mainSessionToken: " + userState.mainSessionToken); 1690e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1691e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1692e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1693e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 16941a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 16951a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String encodeTuneParams(Bundle tuneParams) { 16961a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 16971a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Set<String> keySet = tuneParams.keySet(); 16981a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Iterator<String> it = keySet.iterator(); 16991a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim while (it.hasNext()) { 17001a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim String key = it.next(); 17011a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Object value = tuneParams.get(key); 17021a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (value == null) { 17031a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim continue; 17041a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17051a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(key)); 17061a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append("="); 17071a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(value.toString())); 17081a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (it.hasNext()) { 17091a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(", "); 17101a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17111a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17121a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 17131a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17141a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 17151a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String replaceEscapeCharacters(String src) { 17161a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final char ESCAPE_CHARACTER = '%'; 17171a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final String ENCODING_TARGET_CHARACTERS = "%=,"; 17181a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 17191a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim for (char ch : src.toCharArray()) { 17201a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (ENCODING_TARGET_CHARACTERS.indexOf(ch) >= 0) { 17211a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ESCAPE_CHARACTER); 17221a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17231a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ch); 17241a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17251a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 17261a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1729969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1730969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1731969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1732969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1733969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1734969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1735969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1736969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1737969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1738969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1739969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1740969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1741969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 17423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1743969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1744969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 17453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1746969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1747969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 17485c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 17495c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // A set of all TV content rating system xml uris. 17505c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>(); 17515c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 175272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 175372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 175472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 175572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1757187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1758187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 17593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 17613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 17623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1763969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1764969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1765969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1766969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 176779124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 17684c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // The token of a "main" TV input session. 17694c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private IBinder mainSessionToken = null; 1770783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1771783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // Persistent data store for all internal settings maintained by the TV input manager 1772783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // service. 1773783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private final PersistentDataStore persistentDataStore; 1774783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1775783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private UserState(Context context, int userId) { 1776783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo persistentDataStore = new PersistentDataStore(context, userId); 1777783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 17783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 178072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 178172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 178272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 178372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 178472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 178572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 178672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 178772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 178872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 178972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 179072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 179172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 1792a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee return mSessionTokens.isEmpty(); 179372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 179472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 179572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 179672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 179772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 179872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 179972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1800a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee // removed in releaseSessionLocked(). 180172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 180272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 180372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 180472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 180572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 180672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 180972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 181072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 181172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 181272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 18133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 181472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); 1815d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1816d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 18179e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 1818187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final boolean mIsHardware; 1819187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>(); 18203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1821d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1822d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1823d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 18242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 18253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18269e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState(ComponentName component, int userId) { 18279e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18289e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mConnection = new InputServiceConnection(component, userId); 18299e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mComponent); 18303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1834187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final TvInputInfo mInfo; 1835d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1836d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1837d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 18382b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 183972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1840d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1841d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 1842bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Not null if this session represents an external device connected to a hardware TV input. 1843bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private IBinder mHardwareSessionToken; 18443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1845bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client, 1846bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang int seq, int callingUid, int userId) { 184772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 1848187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mInfo = info; 18492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 18502b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 18512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 18522b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 18532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 18552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 18562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 18572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 18582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 18592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 18602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 18612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 18622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 18632b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 18642b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18652b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 1866bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // If there are any other sessions based on this session, they should be released. 1867bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang UserState userState = getUserStateLocked(mUserId); 1868bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1869bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (mSession != null && mSession == sessionState.mHardwareSessionToken) { 1870bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1871bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mSession.release(); 1872bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1873bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in release", e); 1874bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1875bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1876bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mClient.onSessionReleased(sessionState.mSeq); 1877bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1878bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in onSessionReleased", e); 1879bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1880bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1881bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 188272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 18832b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 18889e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 18893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 18903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18919e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private InputServiceConnection(ComponentName component, int userId) { 18929e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 18943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 18979e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceConnected(ComponentName component, IBinder service) { 18983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 18999e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceConnected(component=" + component + ")"); 19003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1902969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 19039e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 1904d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 19053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1907187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 19089e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState.mCallback = new ServiceCallback(mComponent, mUserId); 19093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1910d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 19113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 19129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 19133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1917d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1918d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 19193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1920969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1921187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19229e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component) 1923187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 19248e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1925187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1926187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1927187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1928187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1929187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 19304f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 19314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1932187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1933187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1934187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1935187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1936187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1937187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1938187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1939187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1940546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo List<HdmiDeviceInfo> deviceInfoList = 1941546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mTvInputHardwareManager.getHdmiDeviceList(); 1942546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo for (HdmiDeviceInfo deviceInfo : deviceInfoList) { 19434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 1944546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 19454f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 1946546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 19474f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19484f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1949969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 19503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19549e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceDisconnected(ComponentName component) { 19553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 19569e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceDisconnected(component=" + component + ")"); 19573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19589e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (!mComponent.equals(component)) { 19592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 19609e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee + mComponent + " (expected), " + component + " (actual)."); 19612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 19632b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 19649e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 19652b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 19662b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 19672b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 19682b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 19692b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 19702b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 19712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 19722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 19732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 19742b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 19752b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 19762b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 1977187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 19782b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19792b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1981187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19829e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component)) { 1983bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1984187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 1985187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1986187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 19879e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(mComponent, mUserId); 19882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 19949e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 19953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 19963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19979e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceCallback(ComponentName component, int userId) { 19989e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 19993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 20003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 20024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 20034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 20044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 20054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 20064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20074f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20084f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20094f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 20109e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputInfo.getId() == null || !mComponent.equals(inputInfo.getComponent())) { 20114f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 20124f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20154f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 20169e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 20174f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 20184f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 20194f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 20224f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 20234f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20244f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 2025187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 20264f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 20274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 20284f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2030187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 20314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 2032546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void addHdmiTvInput(int logicalAddress, TvInputInfo inputInfo) { 20334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20344f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 20354f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 2036546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mTvInputHardwareManager.addHdmiTvInput(logicalAddress, inputInfo); 20374f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 20383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2039187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2040187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2041187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2042187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 20434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 20459e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 2046187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 2047187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 2048187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 2049187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 2050187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 2051187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 2052187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 2053187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2054187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2055187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 2056187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 20574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 2058187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2059187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 2060187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 20613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 206431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 206531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final class LogHandler extends Handler { 206631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_OPEN_ENTRY = 1; 206731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_UPDATE_ENTRY = 2; 206831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_CLOSE_ENTRY = 3; 206931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 207031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public LogHandler(Looper looper) { 207131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 207231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 207431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 207531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 207631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 207731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_OPEN_ENTRY: { 207831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 207931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 208031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 208131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 2082579befecb248162021929ab58ffd23f1724cc6beJae Seo SessionState sessionState = (SessionState) args.arg4; 2083579befecb248162021929ab58ffd23f1724cc6beJae Seo onOpenEntry(uri, channelId, time, sessionState); 208431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 208531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 208631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 208731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_UPDATE_ENTRY: { 208831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 208931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 209031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 209131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 2092579befecb248162021929ab58ffd23f1724cc6beJae Seo SessionState sessionState = (SessionState) args.arg4; 2093579befecb248162021929ab58ffd23f1724cc6beJae Seo onUpdateEntry(uri, channelId, time, sessionState); 209431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 209531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 209631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 209731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_CLOSE_ENTRY: { 209831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 209931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 210031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg2; 210131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onCloseEntry(uri, time); 210231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 210331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 210431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 21066a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 210731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 210831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 211031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 211131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 2112579befecb248162021929ab58ffd23f1724cc6beJae Seo private void onOpenEntry(Uri logUri, long channelId, long watchStarttime, 2113579befecb248162021929ab58ffd23f1724cc6beJae Seo SessionState sessionState) { 2114579befecb248162021929ab58ffd23f1724cc6beJae Seo if (!isChannelSearchable(channelId)) { 2115579befecb248162021929ab58ffd23f1724cc6beJae Seo // Do not log anything about non-searchable channels. 2116579befecb248162021929ab58ffd23f1724cc6beJae Seo synchronized (mLock) { 2117579befecb248162021929ab58ffd23f1724cc6beJae Seo sessionState.mLogUri = null; 2118579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2119579befecb248162021929ab58ffd23f1724cc6beJae Seo mContentResolver.delete(logUri, null, null); 2120579befecb248162021929ab58ffd23f1724cc6beJae Seo return; 2121579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2122579befecb248162021929ab58ffd23f1724cc6beJae Seo 212331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 2124f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_TITLE, 2125f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, 2126f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, 2127bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcbJae Seo TvContract.Programs.COLUMN_SHORT_DESCRIPTION 212831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2129f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " 2130f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND " 2131f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + ">?"; 213231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] selectionArgs = { 213331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(channelId), 213431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime), 213531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime) 213631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2137f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String sortOrder = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + " ASC"; 213831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 213931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 214031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection, 214131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo selection, selectionArgs, sortOrder); 214231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 214331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2144f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, cursor.getString(0)); 2145f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 2146f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo cursor.getLong(1)); 214731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(2); 2148f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 2149f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3)); 2150579befecb248162021929ab58ffd23f1724cc6beJae Seo mContentResolver.update(logUri, values, null, null); 215131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 215231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Schedule an update when the current program ends. 215331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 2154579befecb248162021929ab58ffd23f1724cc6beJae Seo args.arg1 = logUri; 215531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = channelId; 215631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = endTime; 21578d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee args.arg4 = sessionState; 215831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args); 215931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo sendMessageDelayed(msg, endTime - System.currentTimeMillis()); 216031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 216231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 216331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 216431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 2168579befecb248162021929ab58ffd23f1724cc6beJae Seo private void onUpdateEntry(Uri uri, long channelId, long time, SessionState sessionState) { 216931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 21708d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS 217131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 217231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 217331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 217431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(uri, projection, null, null, null); 217531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 21768d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee long watchEndTime = cursor.getLong(0); 217731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Do nothing if the current log entry is already closed. 217831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (watchEndTime > 0) { 217931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 218031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 218131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 21828d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee // Update the watch end time for the current log entry. 218331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2184f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, time); 21858d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee int c = mContentResolver.update(uri, values, null, null); 21868d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } else { 21878d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee // The record has been deleted. 21888d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee synchronized (mLock) { 21898d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee if (!uri.equals(sessionState.mLogUri)) { 21908d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee // If the deleted record is not for the current channel, do not re-open 21918d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee // a log entry for the next program. 21928d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee return; 21938d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 21948d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 21958d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 21968d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee if (cursor != null) { 21978d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee cursor.close(); 21988d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee cursor = null; 21998d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 22008d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee 22018d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee // The current program has just ended. Create a new log entry for the next program. 22028d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee uri = ContentUris.withAppendedId(TvContract.Channels.CONTENT_URI, channelId); 22038d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee projection = new String[] { 22048d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee TvContract.Channels.COLUMN_PACKAGE_NAME 22058d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee }; 22068d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee cursor = mContentResolver.query(uri, projection, null, null, null); 22078d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee if (cursor != null && cursor.moveToNext()) { 22088d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee ContentValues values = new ContentValues(); 22098d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, cursor.getString(0)); 22108d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, time); 22118d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 2212f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 22138d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee Uri newUri = mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, 22148d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee values); 22158d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee 22168d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee synchronized (mLock) { 22178d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee sessionState.mLogUri = newUri; 22188d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 22198d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee 22208d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee // Re-open the current log entry with the next program information. 22218d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee onOpenEntry(newUri, channelId, time, sessionState); 222231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 222331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 222431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 222531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 222631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 222731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 222831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 222931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 223031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onCloseEntry(Uri uri, long watchEndTime) { 223131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2232f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime); 223331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 223431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2235579befecb248162021929ab58ffd23f1724cc6beJae Seo 2236579befecb248162021929ab58ffd23f1724cc6beJae Seo private boolean isChannelSearchable(long channelId) { 2237579befecb248162021929ab58ffd23f1724cc6beJae Seo String[] projection = { TvContract.Channels.COLUMN_SEARCHABLE }; 2238579befecb248162021929ab58ffd23f1724cc6beJae Seo String selection = TvContract.Channels._ID + "=?"; 2239579befecb248162021929ab58ffd23f1724cc6beJae Seo String[] selectionArgs = { String.valueOf(channelId) }; 2240579befecb248162021929ab58ffd23f1724cc6beJae Seo Cursor cursor = null; 2241579befecb248162021929ab58ffd23f1724cc6beJae Seo try { 2242579befecb248162021929ab58ffd23f1724cc6beJae Seo cursor = mContentResolver.query(TvContract.Channels.CONTENT_URI, projection, 2243579befecb248162021929ab58ffd23f1724cc6beJae Seo selection, selectionArgs, null); 2244579befecb248162021929ab58ffd23f1724cc6beJae Seo if (cursor != null && cursor.moveToNext()) { 2245579befecb248162021929ab58ffd23f1724cc6beJae Seo return cursor.getLong(0) == 1 ? true : false; 2246579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2247579befecb248162021929ab58ffd23f1724cc6beJae Seo } finally { 2248579befecb248162021929ab58ffd23f1724cc6beJae Seo if (cursor != null) { 2249579befecb248162021929ab58ffd23f1724cc6beJae Seo cursor.close(); 2250579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2251579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2252579befecb248162021929ab58ffd23f1724cc6beJae Seo // Unless explicitly specified non-searchable, by default the channel is searchable. 2253579befecb248162021929ab58ffd23f1724cc6beJae Seo return true; 2254579befecb248162021929ab58ffd23f1724cc6beJae Seo } 225531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2256969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2257187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 2258187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2259187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 2260969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2261969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 2262969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2263969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2264187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2265187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2266187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 2267187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2268187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2269187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2270187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2271187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2272187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 2273187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 2274187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2275187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 2276187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2277187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2278187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2279187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2280187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2281187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 22824f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 2283187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2284187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2285187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2286187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2287187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2288187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 22894f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 2290187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2291187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 2292187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2293187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2294187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2295187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2296187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2297187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2298546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) { 2299187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 23004f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 23014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 23024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 23034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 23044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2305546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 23064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2307546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 23084f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 23094f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2310187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2311187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2312187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2313187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2314546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) { 2315187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 23164f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 23174f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 23184f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 23194f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 23204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2321546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceRemoved(deviceInfo); 23224f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2323546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e); 23244f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 23254f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2326187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2327187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2328969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 23293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 2330