TvInputManagerService.java revision 546c635ad9a26421fbdf54efa765b5ab0a63c191
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 71631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry, if any. 717d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 71831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 719d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 72031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = System.currentTimeMillis(); 72131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget(); 72231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 72331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 72472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 72572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 72672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 72772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 72872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 72972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 73072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 73172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 734187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 735187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 736187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 737187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 738187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 739187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 740fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 741187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 742fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 743fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 7448e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7458e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7468e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7478e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7488e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7498e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7508e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7528e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7538e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7548e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7568e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7578e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 7588e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7598e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 7608e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7618e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7628e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7638e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 7648e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7658e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 7668e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7678e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7688e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 771969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 772969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 7738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 774969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 775969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 776969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 777969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 778969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 779969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 780969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 781969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 782969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 783969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 784969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 7852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 786969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 7872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 788969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 7892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7902b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 793969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 794969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 795969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 796c88f1916b8ab7f5f75a00375c6fb4873ea5044afJi-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(inputState.mInfo.getComponent()); 797969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 798969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 799187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 800187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 801969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 802969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 803969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 804969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 8058e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 806969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 807969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 808969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 8093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 8103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 8123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 8143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 818969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 819969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 820969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 822969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 827b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 828b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 829b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 830b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 831b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 832b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 833b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 834b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 835b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 836b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 837b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 838b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 839b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 840b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 841b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 842b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8465c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim public List<Uri> getTvContentRatingSystemXmls(int userId) { 8475c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8485c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls"); 8495c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final long identity = Binder.clearCallingIdentity(); 8505c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim try { 8515c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim synchronized (mLock) { 8525c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim UserState userState = getUserStateLocked(resolvedUserId); 8535c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>(); 8545c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet); 8555c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim return ratingSystemXmlUriList; 8565c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8575c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } finally { 8585c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.restoreCallingIdentity(identity); 8595c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8605c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8615c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 8625c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim @Override 863969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 8643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 8663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 870969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 871969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 8728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 873969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 8743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 882969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 8833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 8853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 888969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 889969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 8903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 897783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isParentalControlsEnabled(int userId) { 898783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 899783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isParentalControlsEnabled"); 900783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 901783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 902783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 903783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 904783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isParentalControlsEnabled(); 905783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 906783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 907783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 908783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 909783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 910783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 911783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 912783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void setParentalControlsEnabled(boolean enabled, int userId) { 913783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 914783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 915783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "setParentalControlsEnabled"); 916783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 917783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 918783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 919783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 920783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.setParentalControlsEnabled(enabled); 921783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 922783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 923783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 924783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 925783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 926783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 927783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 928783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isRatingBlocked(String rating, int userId) { 929783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 930783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isRatingBlocked"); 931783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 932783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 933783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 934783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 935783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isRatingBlocked( 936783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 937783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 938783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 939783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 940783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 941783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 942783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 943783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 944783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public List<String> getBlockedRatings(int userId) { 945783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 946783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "getBlockedRatings"); 947783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 948783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 949783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 950783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 951783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo List<String> ratings = new ArrayList<String>(); 952783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo for (TvContentRating rating 953783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo : userState.persistentDataStore.getBlockedRatings()) { 954783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ratings.add(rating.flattenToString()); 955783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 956783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return ratings; 957783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 958783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 959783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 960783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 961783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 962783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 963783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 964783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void addBlockedRating(String rating, int userId) { 965783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 966783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 967783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "addBlockedRating"); 968783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 969783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 970783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 971783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 972783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.addBlockedRating( 973783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 974783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 975783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 976783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 977783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 978783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 979783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 980783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 981783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void removeBlockedRating(String rating, int userId) { 982783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 983783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 984783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "removeBlockedRating"); 985783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 986783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 987783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 988783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 989783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.removeBlockedRating( 990783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 991783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 992783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 993783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 994783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 995783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 996783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 997783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private void ensureParentalControlsPermission() { 998783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo if (mContext.checkCallingPermission( 999783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) 1000783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo != PackageManager.PERMISSION_GRANTED) { 1001783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo throw new SecurityException( 1002783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo "The caller does not have parental controls permission"); 1003783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1004783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1005783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1006783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1007d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 10083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 10093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 10123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 1016187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 1017187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 10183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 1019187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 1020187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 10213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 10232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 10245c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 10252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 10262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 10272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 10292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 1030187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 103172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 10322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 10342b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 10352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10362b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 1037d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 10383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1039d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 1040d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 10417de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 10423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 1043187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 10443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 10533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 10563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 10603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10674c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void setMainSession(IBinder sessionToken, int userId) { 10684c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int callingUid = Binder.getCallingUid(); 10694c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10704c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userId, "setMainSession"); 10714c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final long identity = Binder.clearCallingIdentity(); 10724c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 10734c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (mLock) { 1074982abe693f66037ca265b88057eceb5a3e815182Ji-Hwan Lee UserState userState = getUserStateLocked(resolvedUserId); 1075956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (userState.mainSessionToken == sessionToken) { 10764c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return; 10774c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10784c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1079956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee SessionState newMainSessionState = getSessionStateLocked( 1080956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee sessionToken, callingUid, resolvedUserId); 1081956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (newMainSessionState.mHardwareSessionToken != null) { 1082956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState = getSessionStateLocked( 1083956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState.mHardwareSessionToken, 1084956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee Process.SYSTEM_UID, resolvedUserId); 1085956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee } 1086956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ServiceState newMainServiceState = getServiceStateLocked( 1087956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState.mInfo.getComponent(), resolvedUserId); 1088956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ITvInputSession newMainSession = getSessionLocked(newMainSessionState); 10894c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1090956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ServiceState oldMainServiceState = null; 1091956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ITvInputSession oldMainSession = null; 1092abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (userState.mainSessionToken != null) { 1093956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee SessionState oldMainSessionState = getSessionStateLocked( 1094abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId); 1095956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (oldMainSessionState.mHardwareSessionToken != null) { 1096956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState = getSessionStateLocked( 1097956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState.mHardwareSessionToken, 1098956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee Process.SYSTEM_UID, resolvedUserId); 1099956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee } 1100956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainServiceState = getServiceStateLocked( 1101956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState.mInfo.getComponent(), resolvedUserId); 1102956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSession = getSessionLocked(oldMainSessionState); 1103abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 1104abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 11054c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userState.mainSessionToken = sessionToken; 11064c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1107956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // Inform the new main session first. 1108956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // See {@link TvInputService#onSetMainSession}. 1109956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (newMainServiceState.mIsHardware) { 11104c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 1111956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSession.setMainSession(true); 11124c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 11134c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 11144c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11154c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 1116956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (oldMainSession != null && oldMainServiceState.mIsHardware) { 11174c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 1118956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSession.setMainSession(false); 11194c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 11204c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 11214c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11224c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11234c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11244c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } finally { 11254c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Binder.restoreCallingIdentity(identity); 11264c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11274c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11284c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 11294c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 11303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 11313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 11343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1138bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1139bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1140bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken == null) { 1141bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setSurface(surface); 1142bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } else { 1143bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1144bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setSurface(surface); 1145bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 11463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 11479a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 11483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 1151f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 1152f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 1153f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 1154f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 11553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1160e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 1161e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 1162e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 1163e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1164e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 1165e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 1166e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1167e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 1168e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1169bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1170bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1171bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).dispatchSurfaceChanged(format, width, height); 1172bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1173bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, Process.SYSTEM_UID, 1174bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId).dispatchSurfaceChanged(format, width, height); 1175bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1176e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 1177e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 1178e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1179e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1180e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 1181e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 1182e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1183e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1184e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 1185e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 11863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 1187bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_ON = 1.0f; 1188bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_OFF = 0f; 11893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 11923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1196bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1197bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1198bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setVolume(volume); 1199bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1200bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Here, we let the hardware session know only whether volume is on or 1201bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // off to prevent that the volume is controlled in the both side. 1202bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1203bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f) 1204bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF); 1205bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 12063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 12083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 12153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 12161a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) { 12173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 12183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 12203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 12213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 12233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12241a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( 12251a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim channelUri, params); 1226008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho if (TvContract.isChannelUriForPassthroughTvInput(channelUri)) { 1227008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 1228008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 1229008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 123031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long currentTime = System.currentTimeMillis(); 123131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = ContentUris.parseId(channelUri); 123231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 123331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry first, if any. 123431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 123531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 1236d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 123731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1238d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 123931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = currentTime; 124031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args) 124131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo .sendToTarget(); 124231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 124331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 124431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Create a log entry and fill it later. 1245187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim String packageName = sessionState.mInfo.getServiceInfo().packageName; 124631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 12475c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 1248f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 124931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo currentTime); 1250f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 1251f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 12521a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (params != null) { 12531a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim values.put(TvContract.WatchedPrograms.COLUMN_TUNE_PARAMS, 12541a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim encodeTuneParams(params)); 12551a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 125631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1257d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mLogUri = mContentResolver.insert( 125831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo TvContract.WatchedPrograms.CONTENT_URI, values); 125931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1260d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 126131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = ContentUris.parseId(channelUri); 126231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = currentTime; 1263579befecb248162021929ab58ffd23f1724cc6beJae Seo args.arg4 = sessionState; 126431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget(); 12653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 12673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 12683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12769bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 12779bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1278903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1279903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1280903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1281903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1282903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1283903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1284903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1285903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 12869bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1287903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1288903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1289903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1290903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1291903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1292903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1293903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1294903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1295903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1296903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 12972c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 12982c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 12992c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13002c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 13012c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 13022c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13032c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 13042c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13052c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 13062c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 13072c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 13082c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 13092c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13102c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13112c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 13122c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 13132c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13142c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13152c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 13162c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 131710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void selectTrack(IBinder sessionToken, int type, String trackId, int userId) { 13181f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 13191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13201f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 13211f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 13221f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13231f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 13241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 132610d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo type, trackId); 13271f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 13281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 13291f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13301f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13311f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 13321f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 13331f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13341f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13351f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 13361f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1337a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1338a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1339a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1340a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1341a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1342a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1343a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1344a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1345a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1346a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1347a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1348a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1349a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1350a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1351a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1352a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1353a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1354a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1355a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1356a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1357a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 13589a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 13599a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 13609a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13619a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 13639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 13699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 13719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 13809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 13839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 13899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 13919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 14009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 14019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 14029a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 14039a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 14049a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14059a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 14069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 14089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 14099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 14109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 14119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 14149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 14159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1417c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1418c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1419c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1420969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1421c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1422c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1423c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1424c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1425c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1426c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1427c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1428c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1429c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1430c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1431c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1432c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1433c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1434c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1435969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1436969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1437969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1438c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1439c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1440c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1441c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1442c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1443c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1444c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1445c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1446c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1447c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1448969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1449c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1450c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1451c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1452c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1453c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1454c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1455c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1456c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1457969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1458c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1459c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1460c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1461c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1462c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1463c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1464c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1465c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1466c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1467c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1468c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1469c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1470c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1471c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1472c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1473e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1474e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 1475c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) 1476c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1477c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1478c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1479c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1480c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1481c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1482c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1483c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1484c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1485c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1486c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "getAvailableTvStreamConfigList"); 1487c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1488c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.getAvailableTvStreamConfigList( 1489c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo inputId, callingUid, resolvedUserId); 1490c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1491c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1492c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1493c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1494c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1495c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1496c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config, 1497c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int userId) 1498c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1499c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1500c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1501c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1502c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1503c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1504c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1505c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1506c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1507c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1508c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "captureFrame"); 1509c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1510bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang String hardwareInputId = null; 151179124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 151279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1513bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (userState.inputMap.get(inputId) == null) { 1514bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "Input not found for " + inputId); 1515bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang return false; 1516bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1517bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1518bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mInfo.getId().equals(inputId) 1519bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang && sessionState.mHardwareSessionToken != null) { 1520bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang hardwareInputId = userState.sessionStateMap.get( 1521bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken).mInfo.getId(); 1522bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang break; 1523bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1524bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 152579124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 1526c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.captureFrame( 1527bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang (hardwareInputId != null) ? hardwareInputId : inputId, 152879124a717c09f12c74d587d3977bf33ca37e6420Terry Heo surface, config, callingUid, resolvedUserId); 1529c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1530c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1531c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1532c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1533c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1534c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1535df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo public boolean isSingleSessionActive(int userId) throws RemoteException { 1536df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final long identity = Binder.clearCallingIdentity(); 1537df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int callingUid = Binder.getCallingUid(); 1538df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1539df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo userId, "isSingleSessionActive"); 1540df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo try { 1541df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo synchronized (mLock) { 1542df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1543df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (userState.sessionStateMap.size() == 1) { 1544df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1545df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1546df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo else if (userState.sessionStateMap.size() == 2) { 1547df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo SessionState[] sessionStates = userState.sessionStateMap.values().toArray( 1548df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo new SessionState[0]); 1549df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo // Check if there is a wrapper input. 1550df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (sessionStates[0].mHardwareSessionToken != null 1551df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo || sessionStates[1].mHardwareSessionToken != null) { 1552df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1553df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1554df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1555df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return false; 1556df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1557df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } finally { 1558df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo Binder.restoreCallingIdentity(identity); 1559df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1560df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1561df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo 1562df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo @Override 15630f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1564e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1565e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 15660f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1567e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 15680f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 15690f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1570e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1571e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1572e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1573e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1574e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1575e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1576e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1577e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1578e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1579e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1580e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1581e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1582e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1583e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1584e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1585e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1586e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1587e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1588969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1589e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 15908e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 15918e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1592e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1593e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1594e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1595969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1596e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1597969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1598e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1599e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1600e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1601e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1602e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1603e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1604e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1605e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1606e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1607e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1608e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1609e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1610e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1611e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1612e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1613e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1614e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1615e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1616e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1617e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1618e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1619e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1620e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1621e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1622e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1623e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1624e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1625187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1626e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1627187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1628e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1629e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1630e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1631e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1632e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1633e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1634e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens:"); 1635e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1636e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mClientTokens) { 1637e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1638e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1639e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1640e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1641e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1642e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1643e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1644e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1645e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1646e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1647e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1648e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1649e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1650e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1651e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1652e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1653e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1654e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1655e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1656e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1657e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1658e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1659e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1660e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1661e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1662e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1663e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1664e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1665187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1666e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1667e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1668e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1669e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1670e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1671e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1672e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1673bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang pw.println("mHardwareSessionToken: " + session.mHardwareSessionToken); 1674e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1675e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1676e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1677e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1678969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1679969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1680969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1681969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1682969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1683969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1684969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1685956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee pw.println("mainSessionToken: " + userState.mainSessionToken); 1686e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1687e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1688e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1689e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 16901a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 16911a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String encodeTuneParams(Bundle tuneParams) { 16921a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 16931a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Set<String> keySet = tuneParams.keySet(); 16941a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Iterator<String> it = keySet.iterator(); 16951a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim while (it.hasNext()) { 16961a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim String key = it.next(); 16971a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Object value = tuneParams.get(key); 16981a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (value == null) { 16991a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim continue; 17001a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17011a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(key)); 17021a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append("="); 17031a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(value.toString())); 17041a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (it.hasNext()) { 17051a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(", "); 17061a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17071a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17081a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 17091a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17101a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 17111a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String replaceEscapeCharacters(String src) { 17121a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final char ESCAPE_CHARACTER = '%'; 17131a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final String ENCODING_TARGET_CHARACTERS = "%=,"; 17141a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 17151a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim for (char ch : src.toCharArray()) { 17161a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (ENCODING_TARGET_CHARACTERS.indexOf(ch) >= 0) { 17171a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ESCAPE_CHARACTER); 17181a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17191a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ch); 17201a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17211a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 17221a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1725969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1726969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1727969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1728969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1729969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1730969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1731969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1732969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1733969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1734969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1735969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1736969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1737969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 17383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1739969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1740969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 17413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1742969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1743969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 17445c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 17455c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // A set of all TV content rating system xml uris. 17465c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>(); 17475c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 174872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 174972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 175072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 175172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1753187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1754187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 17553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 17573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 17583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1759969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1760969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1761969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1762969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 176379124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 17644c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // The token of a "main" TV input session. 17654c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private IBinder mainSessionToken = null; 1766783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1767783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // Persistent data store for all internal settings maintained by the TV input manager 1768783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // service. 1769783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private final PersistentDataStore persistentDataStore; 1770783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1771783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private UserState(Context context, int userId) { 1772783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo persistentDataStore = new PersistentDataStore(context, userId); 1773783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 17743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 177672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 177772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 177872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 177972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 178072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 178172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 178272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 178372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 178472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 178572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 178672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 178772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 1788a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee return mSessionTokens.isEmpty(); 178972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 179072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 179172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 179272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 179372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 179472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 179572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1796a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee // removed in releaseSessionLocked(). 179772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 179872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 179972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 180072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 180172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 180272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 180572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 18093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 181072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); 1811d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1812d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 18139e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 1814187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final boolean mIsHardware; 1815187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>(); 18163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1817d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1818d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1819d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 18202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 18213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18229e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState(ComponentName component, int userId) { 18239e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18249e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mConnection = new InputServiceConnection(component, userId); 18259e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mComponent); 18263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1830187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final TvInputInfo mInfo; 1831d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1832d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1833d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 18342b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 183572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1836d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1837d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 1838bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Not null if this session represents an external device connected to a hardware TV input. 1839bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private IBinder mHardwareSessionToken; 18403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1841bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client, 1842bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang int seq, int callingUid, int userId) { 184372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 1844187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mInfo = info; 18452b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 18462b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 18472b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 18482b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 18492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18502b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 18512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 18522b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 18532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 18542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 18552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 18562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 18572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 18582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 18592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 18602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 1862bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // If there are any other sessions based on this session, they should be released. 1863bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang UserState userState = getUserStateLocked(mUserId); 1864bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1865bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (mSession != null && mSession == sessionState.mHardwareSessionToken) { 1866bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1867bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mSession.release(); 1868bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1869bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in release", e); 1870bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1871bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1872bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mClient.onSessionReleased(sessionState.mSeq); 1873bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1874bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in onSessionReleased", e); 1875bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1876bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1877bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 187872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 18792b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 18849e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 18853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 18863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18879e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private InputServiceConnection(ComponentName component, int userId) { 18889e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 18903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 18939e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceConnected(ComponentName component, IBinder service) { 18943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 18959e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceConnected(component=" + component + ")"); 18963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1898969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 18999e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 1900d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 19013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1903187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 19049e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState.mCallback = new ServiceCallback(mComponent, mUserId); 19053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1906d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 19073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 19089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 19093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1913d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1914d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 19153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1916969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1917187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19189e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component) 1919187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 19208e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1921187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1922187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1923187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1924187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1925187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 19264f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 19274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1928187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1929187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1930187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1931187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1932187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1933187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1934187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1935187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1936546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo List<HdmiDeviceInfo> deviceInfoList = 1937546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mTvInputHardwareManager.getHdmiDeviceList(); 1938546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo for (HdmiDeviceInfo deviceInfo : deviceInfoList) { 19394f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 1940546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 19414f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 1942546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 19434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19444f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1945969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 19463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19509e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceDisconnected(ComponentName component) { 19513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 19529e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceDisconnected(component=" + component + ")"); 19533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19549e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (!mComponent.equals(component)) { 19552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 19569e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee + mComponent + " (expected), " + component + " (actual)."); 19572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 19592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 19609e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 19612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 19622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 19632b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 19642b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 19652b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 19662b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 19672b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 19682b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 19692b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 19702b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 19712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 19722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 1973187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 19742b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19752b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19762b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1977187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19789e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component)) { 1979bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1980187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 1981187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1982187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 19839e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(mComponent, mUserId); 19842b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 19909e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 19913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 19923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19939e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceCallback(ComponentName component, int userId) { 19949e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 19953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 19963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19984f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 19994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 20004f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 20014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 20024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 20069e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputInfo.getId() == null || !mComponent.equals(inputInfo.getComponent())) { 20074f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 20084f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20094f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20104f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20114f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 20129e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 20134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 20144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 20154f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20164f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 20184f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 20194f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 2021187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 20224f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 20234f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 20244f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20254f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2026187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 20274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 2028546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void addHdmiTvInput(int logicalAddress, TvInputInfo inputInfo) { 20294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20304f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 20314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 2032546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mTvInputHardwareManager.addHdmiTvInput(logicalAddress, inputInfo); 20334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 20343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2035187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2036187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2037187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2038187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 20394f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 20419e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 2042187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 2043187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 2044187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 2045187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 2046187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 2047187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 2048187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 2049187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2050187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2051187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 2052187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 20534f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 2054187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2055187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 2056187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 20573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 206031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 206131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final class LogHandler extends Handler { 206231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_OPEN_ENTRY = 1; 206331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_UPDATE_ENTRY = 2; 206431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_CLOSE_ENTRY = 3; 206531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 206631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public LogHandler(Looper looper) { 206731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 206831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 206931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 207031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 207131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 207231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 207331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_OPEN_ENTRY: { 207431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 207531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 207631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 207731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 2078579befecb248162021929ab58ffd23f1724cc6beJae Seo SessionState sessionState = (SessionState) args.arg4; 2079579befecb248162021929ab58ffd23f1724cc6beJae Seo onOpenEntry(uri, channelId, time, sessionState); 208031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 208131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 208231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 208331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_UPDATE_ENTRY: { 208431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 208531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 208631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 208731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 2088579befecb248162021929ab58ffd23f1724cc6beJae Seo SessionState sessionState = (SessionState) args.arg4; 2089579befecb248162021929ab58ffd23f1724cc6beJae Seo onUpdateEntry(uri, channelId, time, sessionState); 209031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 209131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 209231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 209331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_CLOSE_ENTRY: { 209431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 209531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 209631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg2; 209731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onCloseEntry(uri, time); 209831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 209931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 210031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 21026a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 210331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 210431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 2108579befecb248162021929ab58ffd23f1724cc6beJae Seo private void onOpenEntry(Uri logUri, long channelId, long watchStarttime, 2109579befecb248162021929ab58ffd23f1724cc6beJae Seo SessionState sessionState) { 2110579befecb248162021929ab58ffd23f1724cc6beJae Seo if (!isChannelSearchable(channelId)) { 2111579befecb248162021929ab58ffd23f1724cc6beJae Seo // Do not log anything about non-searchable channels. 2112579befecb248162021929ab58ffd23f1724cc6beJae Seo synchronized (mLock) { 2113579befecb248162021929ab58ffd23f1724cc6beJae Seo sessionState.mLogUri = null; 2114579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2115579befecb248162021929ab58ffd23f1724cc6beJae Seo mContentResolver.delete(logUri, null, null); 2116579befecb248162021929ab58ffd23f1724cc6beJae Seo return; 2117579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2118579befecb248162021929ab58ffd23f1724cc6beJae Seo 211931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 2120f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_TITLE, 2121f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, 2122f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, 2123bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcbJae Seo TvContract.Programs.COLUMN_SHORT_DESCRIPTION 212431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2125f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " 2126f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND " 2127f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + ">?"; 212831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] selectionArgs = { 212931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(channelId), 213031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime), 213131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime) 213231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2133f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String sortOrder = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + " ASC"; 213431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 213531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 213631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection, 213731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo selection, selectionArgs, sortOrder); 213831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 213931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2140f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, cursor.getString(0)); 2141f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 2142f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo cursor.getLong(1)); 214331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(2); 2144f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 2145f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3)); 2146579befecb248162021929ab58ffd23f1724cc6beJae Seo mContentResolver.update(logUri, values, null, null); 214731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 214831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Schedule an update when the current program ends. 214931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 2150579befecb248162021929ab58ffd23f1724cc6beJae Seo args.arg1 = logUri; 215131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = channelId; 215231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = endTime; 215331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args); 215431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo sendMessageDelayed(msg, endTime - System.currentTimeMillis()); 215531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 215631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 215731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 215831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 215931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 2163579befecb248162021929ab58ffd23f1724cc6beJae Seo private void onUpdateEntry(Uri uri, long channelId, long time, SessionState sessionState) { 216431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 2165f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 2166f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 2167f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_TITLE, 2168f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 2169f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, 2170f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_DESCRIPTION 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()) { 217631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchStartTime = cursor.getLong(0); 217731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchEndTime = cursor.getLong(1); 217831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String title = cursor.getString(2); 217931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long startTime = cursor.getLong(3); 218031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(4); 218131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String description = cursor.getString(5); 218231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 218331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Do nothing if the current log entry is already closed. 218431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (watchEndTime > 0) { 218531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 218631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 218731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 218831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // The current program has just ended. Create a (complete) log entry off the 218931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // current entry. 219031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2191f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 219231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo watchStartTime); 2193f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, time); 2194f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 2195f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, title); 2196f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, startTime); 2197f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 2198f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, description); 219931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 220031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 220131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 220231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 220331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 220431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 220531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 220631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Re-open the current log entry with the next program information. 2207579befecb248162021929ab58ffd23f1724cc6beJae Seo onOpenEntry(uri, channelId, time, sessionState); 220831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 220931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 221031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onCloseEntry(Uri uri, long watchEndTime) { 221131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2212f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime); 221331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 221431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2215579befecb248162021929ab58ffd23f1724cc6beJae Seo 2216579befecb248162021929ab58ffd23f1724cc6beJae Seo private boolean isChannelSearchable(long channelId) { 2217579befecb248162021929ab58ffd23f1724cc6beJae Seo String[] projection = { TvContract.Channels.COLUMN_SEARCHABLE }; 2218579befecb248162021929ab58ffd23f1724cc6beJae Seo String selection = TvContract.Channels._ID + "=?"; 2219579befecb248162021929ab58ffd23f1724cc6beJae Seo String[] selectionArgs = { String.valueOf(channelId) }; 2220579befecb248162021929ab58ffd23f1724cc6beJae Seo Cursor cursor = null; 2221579befecb248162021929ab58ffd23f1724cc6beJae Seo try { 2222579befecb248162021929ab58ffd23f1724cc6beJae Seo cursor = mContentResolver.query(TvContract.Channels.CONTENT_URI, projection, 2223579befecb248162021929ab58ffd23f1724cc6beJae Seo selection, selectionArgs, null); 2224579befecb248162021929ab58ffd23f1724cc6beJae Seo if (cursor != null && cursor.moveToNext()) { 2225579befecb248162021929ab58ffd23f1724cc6beJae Seo return cursor.getLong(0) == 1 ? true : false; 2226579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2227579befecb248162021929ab58ffd23f1724cc6beJae Seo } finally { 2228579befecb248162021929ab58ffd23f1724cc6beJae Seo if (cursor != null) { 2229579befecb248162021929ab58ffd23f1724cc6beJae Seo cursor.close(); 2230579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2231579befecb248162021929ab58ffd23f1724cc6beJae Seo } 2232579befecb248162021929ab58ffd23f1724cc6beJae Seo // Unless explicitly specified non-searchable, by default the channel is searchable. 2233579befecb248162021929ab58ffd23f1724cc6beJae Seo return true; 2234579befecb248162021929ab58ffd23f1724cc6beJae Seo } 223531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2236969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2237187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 2238187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2239187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 2240969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2241969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 2242969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2243969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2244187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2245187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2246187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 2247187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2248187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2249187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2250187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2251187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2252187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 2253187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 2254187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2255187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 2256187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2257187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2258187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2259187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2260187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2261187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 22624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 2263187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2264187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2265187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2266187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2267187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2268187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 22694f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 2270187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2271187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 2272187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2273187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2274187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2275187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2276187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2277187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2278546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) { 2279187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 22804f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 22814f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 22824f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 22834f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 22844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2285546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 22864f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2287546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 22884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 22894f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2290187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2291187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2292187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2293187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2294546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) { 2295187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 22964f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 22974f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 22984f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 22994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 23004f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2301546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceRemoved(deviceInfo); 23024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2303546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e); 23044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 23054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2306187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2307187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2308969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 23093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 2310