TvInputManagerService.java revision bd2fa2c02d916a9b6c62f8fd8701d779c00bd68d
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; 385c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Limimport android.content.res.Resources; 3931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.database.Cursor; 409a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.graphics.Rect; 41187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport android.hardware.hdmi.HdmiCecDeviceInfo; 42d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputClient; 43d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardware; 44d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardwareCallback; 45d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputManager; 46969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.media.tv.ITvInputManagerCallback; 47d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputService; 48d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputServiceCallback; 49d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSession; 50d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSessionCallback; 51783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seoimport android.media.tv.TvContentRating; 52d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvContract; 53d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputHardwareInfo; 54d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputInfo; 551a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Limimport android.media.tv.TvInputManager; 56d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputService; 57c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heoimport android.media.tv.TvStreamConfig; 581f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport android.media.tv.TvTrackInfo; 593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.net.Uri; 603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Binder; 61832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 6231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Handler; 633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.IBinder; 6431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Looper; 6531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Message; 663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Process; 673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.RemoteException; 683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.UserHandle; 699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Slog; 703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.util.SparseArray; 716a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputChannel; 723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.view.Surface; 733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.internal.content.PackageMonitor; 7531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.internal.os.SomeArgs; 76e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport com.android.internal.util.IndentingPrintWriter; 7731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.server.IoThread; 783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.server.SystemService; 793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 80e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport org.xmlpull.v1.XmlPullParserException; 81e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee 82e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.FileDescriptor; 83e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport java.io.IOException; 84e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.PrintWriter; 853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.ArrayList; 863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.HashMap; 875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.HashSet; 88187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport java.util.Iterator; 893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.List; 903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.Map; 915c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.Set; 923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/** This class provides a system service that manages television inputs. */ 943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopublic final class TvInputManagerService extends SystemService { 953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // STOPSHIP: Turn debugging off. 963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final boolean DEBUG = true; 973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final String TAG = "TvInputManagerService"; 983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Context mContext; 100c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareManager mTvInputHardwareManager; 1013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final ContentResolver mContentResolver; 10331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A global lock. 1053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Object mLock = new Object(); 1063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // ID of the current user. 1083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int mCurrentUserId = UserHandle.USER_OWNER; 1093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A map from user id to UserState. 1113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 1123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final Handler mLogHandler; 11431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 12031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler = new LogHandler(IoThread.get().getLooper()); 12131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 122187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); 12331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 125783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo mUserStates.put(mCurrentUserId, new UserState(mContext, mCurrentUserId)); 1263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onStart() { 1313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo publishBinderService(Context.TV_INPUT_SERVICE, new BinderService()); 1323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1340ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee @Override 1350ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee public void onBootPhase(int phase) { 1360ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1370ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee registerBroadcastReceivers(); 138187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 1390ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee synchronized (mLock) { 1400ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee buildTvInputListLocked(mCurrentUserId); 1410ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1420ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 143969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.onBootPhase(phase); 1440ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1450ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee 1463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void registerBroadcastReceivers() { 1473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageMonitor monitor = new PackageMonitor() { 1483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSomePackagesChanged() { 1503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(mCurrentUserId); 1523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1555c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo @Override 1565c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo public void onPackageRemoved(String packageName, int uid) { 1575c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo synchronized (mLock) { 1585c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo UserState userState = getUserStateLocked(mCurrentUserId); 159969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (!userState.packageSet.contains(packageName)) { 1605c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo // Not a TV input package. 1615c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo return; 1625c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1635c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1645c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1655c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ArrayList<ContentProviderOperation> operations = 1665c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo new ArrayList<ContentProviderOperation>(); 1675c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1685c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; 1695c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String[] selectionArgs = { packageName }; 1705c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1715c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI) 1725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1735c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI) 1745c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1755c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation 1765c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .newDelete(TvContract.WatchedPrograms.CONTENT_URI) 1775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ContentProviderResult[] results = null; 1805c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo try { 1815c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations); 1825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } catch (RemoteException | OperationApplicationException e) { 1835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.e(TAG, "error in applyBatch" + e); 1845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo if (DEBUG) { 1875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid 1885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo + ")"); 1895c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "results=" + results); 1905c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1915c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 1933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo monitor.register(mContext, null, UserHandle.ALL, true); 1943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo IntentFilter intentFilter = new IntentFilter(); 1963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 1973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext.registerReceiverAsUser(new BroadcastReceiver() { 1993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 2003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onReceive(Context context, Intent intent) { 2013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String action = intent.getAction(); 2023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (Intent.ACTION_USER_SWITCHED.equals(action)) { 2033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 2053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }, UserHandle.ALL, intentFilter, null, null); 2093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2119e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private static boolean hasHardwarePermission(PackageManager pm, ComponentName component) { 212187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, 2139e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee component.getPackageName()) == PackageManager.PERMISSION_GRANTED; 214187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 215187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void buildTvInputListLocked(int userId) { 2173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 218969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2198e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 220969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.packageSet.clear(); 2213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2229a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (DEBUG) Slog.d(TAG, "buildTvInputList"); 2233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageManager pm = mContext.getPackageManager(); 2243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo List<ResolveInfo> services = pm.queryIntentServices( 225e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee new Intent(TvInputService.SERVICE_INTERFACE), 226e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 2274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 2283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ResolveInfo ri : services) { 2293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ServiceInfo si = ri.serviceInfo; 2303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { 2319a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission " 2323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + android.Manifest.permission.BIND_TV_INPUT); 2333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo continue; 2343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 235e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee try { 2364f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.clear(); 2379e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ComponentName component = new ComponentName(si.packageName, si.name); 2389e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (hasHardwarePermission(pm, component)) { 2399e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 240187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState == null) { 241187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // We see this hardware TV input service for the first time; we need to 242187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // prepare the ServiceState object so that we can connect to the service and 243187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // let it add TvInputInfo objects to mInputList if there's any. 2449e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState = new ServiceState(component, userId); 2459e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee userState.serviceStateMap.put(component, serviceState); 246187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2474f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.addAll(serviceState.mInputList); 248187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 249187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2504f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); 251187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 252187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2534f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (TvInputInfo info : inputList) { 254187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (DEBUG) Slog.d(TAG, "add " + info.getId()); 2558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim TvInputState state = userState.inputMap.get(info.getId()); 256187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (state == null) { 257187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state = new TvInputState(); 258187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 259187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state.mInfo = info; 2608e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim inputMap.put(info.getId(), state); 261969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 262226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 263226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Reconnect the service if existing input is updated. 2649e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(component, userId); 265187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 266187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.packageSet.add(si.packageName); 267e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } catch (IOException | XmlPullParserException e) { 268e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee Slog.e(TAG, "Can't load TV input " + si.name, e); 269e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 2703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : inputMap.keySet()) { 2738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!userState.inputMap.containsKey(inputId)) { 2748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputAddedLocked(userState, inputId); 2758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : userState.inputMap.keySet()) { 2798e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!inputMap.containsKey(inputId)) { 2808e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputRemovedLocked(userState, inputId); 2818e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2828e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2838e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2848e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap.clear(); 2858e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap = inputMap; 2865c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 2875c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Resources r = Resources.getSystem(); 2885c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.clear(); 2895c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(TvContentRating.SYSTEM_CONTENT_RATING_SYSTEM_XML); 2905c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim for (TvInputState state : userState.inputMap.values()) { 2915c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri(); 2925c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim if (ratingSystemXmlUri != null) { 2935c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // TODO: need to check the validation of xml format and the duplication of rating 2945c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // systems. 2955c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(state.mInfo.getRatingSystemXmlUri()); 2965c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2975c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 3063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 3073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 3083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 311783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState = new UserState(mContext, userId); 3123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 3143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 3153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 3193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 320b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 321b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 322b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 323b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 3243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 3253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 326d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 3273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 328d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 3293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3309a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 3313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 3353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 3373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 338d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 3393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 340d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 3413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3429a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 3433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 34572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.clear(); 346d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 3473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 3493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 35072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 35172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 3523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 3533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3649e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState getServiceStateLocked(ComponentName component, int userId) { 3653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3669e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 3673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 3689e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee throw new IllegalStateException("Service state not found for " + component + " (userId=" 3697de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3742b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 381d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3894c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return getSessionLocked(getSessionStateLocked(sessionToken, callingUid, userId)); 3904c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 3914c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 3924c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private ITvInputSession getSessionLocked(SessionState sessionState) { 393d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3954c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee throw new IllegalStateException("Session not yet created for token " 3964c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee + sessionState.mSessionToken); 3973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 3993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 4013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 4023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 4033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 4043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 4053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 407187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean shouldMaintainConnection(ServiceState serviceState) { 408187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return !serviceState.mClientTokens.isEmpty() 409187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || !serviceState.mSessionTokens.isEmpty() 410187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || serviceState.mIsHardware; 411187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // TODO: Find a way to maintain connection only when necessary. 412187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 413187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 4149e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private void updateServiceConnectionLocked(ComponentName component, int userId) { 4153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 4169e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 4173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 4183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting) { 4212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!serviceState.mSessionTokens.isEmpty()) { 4222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // wait until all the sessions are removed. 4232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 4242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 4252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = false; 4262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 427187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean maintainConnection = shouldMaintainConnection(serviceState); 428187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mService == null && maintainConnection && userId == mCurrentUserId) { 4293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is not yet connected but its state indicates that we 4303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // have pending requests. Then, connect the service. 431d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mBound) { 4323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // We have already bound to the service so we don't try to bind again until after we 4333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // unbind later on. 4343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4379e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "bindServiceAsUser(service=" + component + ", userId=" + userId + ")"); 4383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 439d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim 4409e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component); 441226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Binding service may fail if the service is updating. 442226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // In that case, the connection will be revived in buildTvInputListLocked called by 443226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // onSomePackagesChanged. 444e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee serviceState.mBound = mContext.bindServiceAsUser( 445e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); 446187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (serviceState.mService != null && !maintainConnection) { 4473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is already connected but its state indicates that we have 4483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // nothing to do with it. Then, disconnect the service. 4493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4509e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "unbindService(service=" + component + ")"); 4513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 452d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 4539e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee userState.serviceStateMap.remove(component); 4543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 45772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 45872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 45972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 46072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 46172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 46272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 46372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 46472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 46572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 46672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 46772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 46872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4707de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 47172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 47272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 474187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")"); 4753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4766a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4776a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4786a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 482bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) { 4833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 484187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")"); 4853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 487d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 488bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken = harewareSessionToken; 489fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 490fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 491187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 492187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 493fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 4942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 4952b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 4962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 4972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 4982b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 49972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 50072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 50172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 50272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 50372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 50472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 50572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 50672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 507187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 508187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), sessionToken, channels[0], 509187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mSeq); 510fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 5116a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 5123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 514832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 515832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 5161f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 517a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 518a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 520a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 521a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 522a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 523a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 524a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 5261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 5271f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 5281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 5291f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 530a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5311f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 532a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 533a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 534a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 535a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 536a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 5371f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onTrackInfoChanged(List<TvTrackInfo> tracks) { 538a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 539a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5401f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onTrackInfoChanged(" + tracks + ")"); 541a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 542a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 543a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 544a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 545a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5461f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onTrackInfoChanged(tracks, 547a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang sessionState.mSeq); 548a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5491f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onTrackInfoChanged"); 550b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 551b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 552b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 553b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 554b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 555d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo public void onTrackSelectionChanged(List<TvTrackInfo> selectedTracks) { 556d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo synchronized (mLock) { 557d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (DEBUG) { 558d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo Slog.d(TAG, "onTrackSelectionChanged(" + selectedTracks + ")"); 559d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 560d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 561d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo return; 562d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 563d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo try { 564d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo sessionState.mClient.onTrackSelectionChanged(selectedTracks, 565d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo sessionState.mSeq); 566d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } catch (RemoteException e) { 567d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo Slog.e(TAG, "error in onTrackSelectionChanged"); 568d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 569d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 570d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 571d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 572d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo @Override 5739b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 5749b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5759b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5769b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 5779b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5789b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5799b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5809b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5819b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5829b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 5839b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5849b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5859b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5869b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5879b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5889b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5899b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 5909b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 5919b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5929b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5939b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 5949b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5959b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5969b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5979b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5989b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5999b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 6009b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 6019b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 6029b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6039b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6049b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6059b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 6069b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 607bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed() { 608bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo synchronized (mLock) { 609bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 610bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.d(TAG, "onContentAllowed()"); 611bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 612bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 613bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo return; 614bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 615bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo try { 616bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo sessionState.mClient.onContentAllowed(sessionState.mSeq); 617bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } catch (RemoteException e) { 618bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.e(TAG, "error in onContentAllowed"); 619bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 620bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 621bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 622bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 623bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 6246057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String rating) { 6256057102dbb746593a7d59cf377c969b62e38c664Jae Seo synchronized (mLock) { 6266057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (DEBUG) { 6276057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.d(TAG, "onContentBlocked()"); 6286057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6296057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 6306057102dbb746593a7d59cf377c969b62e38c664Jae Seo return; 6316057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6326057102dbb746593a7d59cf377c969b62e38c664Jae Seo try { 6336057102dbb746593a7d59cf377c969b62e38c664Jae Seo sessionState.mClient.onContentBlocked(rating, sessionState.mSeq); 6346057102dbb746593a7d59cf377c969b62e38c664Jae Seo } catch (RemoteException e) { 6356057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.e(TAG, "error in onContentBlocked"); 6366057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6376057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6386057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6396057102dbb746593a7d59cf377c969b62e38c664Jae Seo 6406057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 641832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 642832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 643832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 644832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 645832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 646832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 647832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 648832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 649832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 650832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 651832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 652832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 653832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 654832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 655832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 656832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 6573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 6583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 6603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 661187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim service.createSession(channels[1], callback, sessionState.mInfo.getId()); 6623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 6639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 664fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 665187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null, 666187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim null, sessionState.mSeq); 6673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6686a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 6693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 671d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 6725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 6733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 674d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 6753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 6769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 6773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6782b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 6812b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 6822b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 6832b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 6842b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 6852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 6862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 6872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 6893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6902b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 6913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 693fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 694fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 695abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 696abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken = null; 697abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 698abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 699abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee // Remove the session state from the global session state map of the current user. 700fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 701fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 70231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry, if any. 703d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 70431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 705d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 70631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = System.currentTimeMillis(); 70731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget(); 70831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 70931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 71072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 71172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 71272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 71372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 71472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 71572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 71672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 71772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 71872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 71972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 720187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 721187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 722187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 723187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 724187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 725187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 726fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 727187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 728fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 729fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 7308e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7318e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7328e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7338e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7348e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7358e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7368e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7378e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7388e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7398e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7408e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7418e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7428e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7438e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 7448e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7458e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 7468e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7478e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7488e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7498e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 7508e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 7528e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7538e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7548e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7568e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 757969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 758969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 7598e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 760969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 761969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 762969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 763969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 764969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 765969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 766969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 767969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 768969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 769969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 770969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 7712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 772969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 7732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 774969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 7752b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7762b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7772b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7782b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 779969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 780969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 781969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 782c88f1916b8ab7f5f75a00375c6fb4873ea5044afJi-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(inputState.mInfo.getComponent()); 783969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 784969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 785187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 786187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 787969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 788969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 789969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 790969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 7918e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 792969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 793969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 794969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 7953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 7963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 7973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 7983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 7993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 8003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 804969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 805969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 806969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 808969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 813b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 814b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 815b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 816b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 817b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 818b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 819b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 820b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 821b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 822b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 823b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 824b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 825b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 826b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 827b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 828b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8325c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim public List<Uri> getTvContentRatingSystemXmls(int userId) { 8335c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8345c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls"); 8355c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final long identity = Binder.clearCallingIdentity(); 8365c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim try { 8375c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim synchronized (mLock) { 8385c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim UserState userState = getUserStateLocked(resolvedUserId); 8395c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>(); 8405c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet); 8415c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim return ratingSystemXmlUriList; 8425c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8435c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } finally { 8445c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.restoreCallingIdentity(identity); 8455c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8465c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8475c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 8485c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim @Override 849969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 8503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 8523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 856969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 857969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 8588e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 859969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 8603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 868969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 8713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 874969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 875969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 8763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 883783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isParentalControlsEnabled(int userId) { 884783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 885783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isParentalControlsEnabled"); 886783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 887783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 888783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 889783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 890783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isParentalControlsEnabled(); 891783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 892783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 893783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 894783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 895783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 896783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 897783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 898783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void setParentalControlsEnabled(boolean enabled, int userId) { 899783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 900783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 901783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "setParentalControlsEnabled"); 902783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 903783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 904783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 905783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 906783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.setParentalControlsEnabled(enabled); 907783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 908783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 909783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 910783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 911783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 912783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 913783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 914783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isRatingBlocked(String rating, int userId) { 915783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 916783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isRatingBlocked"); 917783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 918783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 919783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 920783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 921783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isRatingBlocked( 922783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 923783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 924783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 925783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 926783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 927783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 928783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 929783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 930783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public List<String> getBlockedRatings(int userId) { 931783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 932783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "getBlockedRatings"); 933783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 934783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 935783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 936783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 937783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo List<String> ratings = new ArrayList<String>(); 938783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo for (TvContentRating rating 939783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo : userState.persistentDataStore.getBlockedRatings()) { 940783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ratings.add(rating.flattenToString()); 941783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 942783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return ratings; 943783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 944783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 945783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 946783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 947783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 948783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 949783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 950783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void addBlockedRating(String rating, int userId) { 951783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 952783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 953783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "addBlockedRating"); 954783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 955783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 956783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 957783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 958783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.addBlockedRating( 959783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 960783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 961783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 962783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 963783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 964783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 965783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 966783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 967783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void removeBlockedRating(String rating, int userId) { 968783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 969783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 970783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "removeBlockedRating"); 971783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 972783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 973783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 974783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 975783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.removeBlockedRating( 976783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 977783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 978783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 979783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 980783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 981783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 982783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 983783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private void ensureParentalControlsPermission() { 984783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo if (mContext.checkCallingPermission( 985783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) 986783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo != PackageManager.PERMISSION_GRANTED) { 987783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo throw new SecurityException( 988783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo "The caller does not have parental controls permission"); 989783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 990783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 991783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 992783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 993d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 9943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 9953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 9963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 9983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 1002187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 1003187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 10043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 1005187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 1006187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 10073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10082b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 10092b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 10105c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 10112b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 10122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 10132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 10152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 1016187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 101772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 10182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 10202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 10212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 1023d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 10243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1025d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 1026d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 10277de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 10283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 1029187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 10303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 10393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 10423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10452b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 10463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10534c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void setMainSession(IBinder sessionToken, int userId) { 10544c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int callingUid = Binder.getCallingUid(); 10554c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10564c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userId, "setMainSession"); 10574c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final long identity = Binder.clearCallingIdentity(); 10584c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 10594c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (mLock) { 1060982abe693f66037ca265b88057eceb5a3e815182Ji-Hwan Lee UserState userState = getUserStateLocked(resolvedUserId); 10614c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee if (sessionToken == userState.mainSessionToken) { 10624c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return; 10634c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10644c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 10654c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 10664c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee resolvedUserId); 10674c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked( 10684c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee sessionState.mInfo.getComponent(), resolvedUserId); 10694c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee ITvInputSession session = getSessionLocked(sessionState); 10704c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1071abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee ServiceState prevMainServiceState = null; 1072abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee ITvInputSession prevMainSession = null; 1073abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (userState.mainSessionToken != null) { 1074abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee SessionState prevMainSessionState = getSessionStateLocked( 1075abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId); 1076abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee prevMainServiceState = getServiceStateLocked( 1077abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee prevMainSessionState.mInfo.getComponent(), resolvedUserId); 1078abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee prevMainSession = getSessionLocked(prevMainSessionState); 1079abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 1080abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 10814c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userState.mainSessionToken = sessionToken; 10824c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 10834c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // Inform the new main session first. See {@link TvInputService#onSetMain}. 10844c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee if (serviceState.mIsHardware) { 10854c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 10864c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee session.setMainSession(true); 10874c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 10884c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 10894c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10904c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 1091abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (prevMainSession != null && prevMainServiceState.mIsHardware) { 10924c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 10934c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee prevMainSession.setMainSession(false); 10944c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 10954c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 10964c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10974c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10984c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10994c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } finally { 11004c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Binder.restoreCallingIdentity(identity); 11014c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11024c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11034c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 11044c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 11053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 11063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 11093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1113bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1114bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1115bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken == null) { 1116bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setSurface(surface); 1117bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } else { 1118bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1119bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setSurface(surface); 1120bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 11213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 11229a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 11233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 1126f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 1127f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 1128f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 1129f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 11303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1135e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 1136e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 1137e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 1138e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1139e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 1140e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 1141e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1142e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 1143e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1144bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1145bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1146bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).dispatchSurfaceChanged(format, width, height); 1147bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1148bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, Process.SYSTEM_UID, 1149bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId).dispatchSurfaceChanged(format, width, height); 1150bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1151e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 1152e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 1153e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1154e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1155e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 1156e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 1157e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1158e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1159e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 1160e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 11613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 1162bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_ON = 1.0f; 1163bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_OFF = 0f; 11643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 11673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1171bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1172bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1173bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setVolume(volume); 1174bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1175bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Here, we let the hardware session know only whether volume is on or 1176bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // off to prevent that the volume is controlled in the both side. 1177bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1178bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f) 1179bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF); 1180bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 11813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 11829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 11833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 11863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 11911a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) { 11923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 11953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11991a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( 12001a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim channelUri, params); 1201008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho if (TvContract.isChannelUriForPassthroughTvInput(channelUri)) { 1202008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 1203008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 1204008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 120531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long currentTime = System.currentTimeMillis(); 120631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = ContentUris.parseId(channelUri); 120731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 120831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry first, if any. 120931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 121031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 1211d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 121231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1213d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 121431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = currentTime; 121531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args) 121631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo .sendToTarget(); 121731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 121831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 121931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Create a log entry and fill it later. 1220187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim String packageName = sessionState.mInfo.getServiceInfo().packageName; 122131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 12225c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 1223f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 122431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo currentTime); 1225f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 1226f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 12271a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (params != null) { 12281a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim values.put(TvContract.WatchedPrograms.COLUMN_TUNE_PARAMS, 12291a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim encodeTuneParams(params)); 12301a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 123131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1232d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mLogUri = mContentResolver.insert( 123331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo TvContract.WatchedPrograms.CONTENT_URI, values); 123431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1235d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 123631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = ContentUris.parseId(channelUri); 123731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = currentTime; 123831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget(); 12393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12409a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 12413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 12423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12489a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12499a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12509bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 12519bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1252903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1253903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1254903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1255903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1256903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1257903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1258903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1259903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 12609bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1261903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1262903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1263903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1264903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1265903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1266903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1267903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1268903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1269903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1270903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 12712c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 12722c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 12732c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12742c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 12752c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 12762c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 12772c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 12782c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 12792c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 12802c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 12812c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 12822c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 12832c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12842c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12852c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 12862c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 12872c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12882c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 12892c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 12902c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 12911f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void selectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 12921f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 12931f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12941f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 12951f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 12961f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 12971f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 12981f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 12991f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 13001f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 13011f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 13021f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 13031f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13041f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13051f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 13061f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 13071f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13081f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13091f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 13101f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 13111f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void unselectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 13121f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 13131f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13141f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "unselectTrack"); 13151f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 13161f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13171f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 13181f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).unselectTrack( 13201f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 13211f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 13221f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in unselectTrack", e); 13231f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 13261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 13271f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13291f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 13301f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1331a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1332a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1333a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1334a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1335a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1336a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1337a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1338a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1339a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1340a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1341a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1342a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1343a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1344a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1345a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1346a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1347a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1348a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1349a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1350a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1351a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 13529a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 13539a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 13549a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13559a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13569a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 13579a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13589a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13599a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13609a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13619a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 13639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 13659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 13749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 13779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 13839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 13859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 13949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 13979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 14009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 14029a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 14039a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 14049a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 14059a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 14089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 14099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1411c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1412c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1413c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1414969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1415c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1416c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1417c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1418c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1419c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1420c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1421c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1422c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1423c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1424c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1425c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1426c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1427c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1428c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1429969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1430969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1431969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1432c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1433c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1434c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1435c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1436c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1437c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1438c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1439c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1440c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1441c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1442969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1443c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1444c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1445c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1446c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1447c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1448c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1449c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1450c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1451969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1452c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1453c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1454c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1455c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1456c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1457c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1458c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1459c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1460c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1461c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1462c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1463c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1464c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1465c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1466c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1467e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1468e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 1469c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) 1470c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1471c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1472c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1473c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1474c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1475c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1476c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1477c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1478c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1479c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1480c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "getAvailableTvStreamConfigList"); 1481c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1482c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.getAvailableTvStreamConfigList( 1483c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo inputId, callingUid, resolvedUserId); 1484c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1485c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1486c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1487c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1488c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1489c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1490c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config, 1491c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int userId) 1492c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1493c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1494c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1495c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1496c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1497c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1498c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1499c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1500c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1501c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1502c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "captureFrame"); 1503c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1504bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang String hardwareInputId = null; 150579124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 150679124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1507bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (userState.inputMap.get(inputId) == null) { 1508bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "Input not found for " + inputId); 1509bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang return false; 1510bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1511bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1512bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mInfo.getId().equals(inputId) 1513bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang && sessionState.mHardwareSessionToken != null) { 1514bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang hardwareInputId = userState.sessionStateMap.get( 1515bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken).mInfo.getId(); 1516bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang break; 1517bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1518bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 151979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 1520c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.captureFrame( 1521bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang (hardwareInputId != null) ? hardwareInputId : inputId, 152279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo surface, config, callingUid, resolvedUserId); 1523c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1524c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1525c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1526c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1527c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1528c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 15290f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1530e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1531e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 15320f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1533e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 15340f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 15350f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1536e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1537e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1538e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1539e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1540e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1541e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1542e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1543e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1544e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1545e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1546e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1547e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1548e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1549e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1550e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1551e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1552e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1553e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1554969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1555e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 15568e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 15578e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1558e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1559e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1560e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1561969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1562e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1563969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1564e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1565e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1566e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1567e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1568e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1569e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1570e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1571e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1572e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1573e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1574e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1575e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1576e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1577e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1578e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1579e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1580e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1581e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1582e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1583e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1584e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1585e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1586e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1587e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1588e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1589e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1590e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1591187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1592e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1593187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1594e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1595e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1596e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1597e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1598e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1599e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1600e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens:"); 1601e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1602e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mClientTokens) { 1603e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1604e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1605e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1606e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1607e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1608e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1609e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1610e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1611e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1612e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1613e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1614e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1615e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1616e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1617e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1618e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1619e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1620e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1621e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1622e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1623e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1624e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1625e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1626e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1627e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1628e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1629e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1630e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1631187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1632e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1633e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1634e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1635e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1636e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1637e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1638e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1639bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang pw.println("mHardwareSessionToken: " + session.mHardwareSessionToken); 1640e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1641e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1642e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1643e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1644969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1645969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1646969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1647969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1648969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1649969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1650969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1651e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1652e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1653e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1654e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 16551a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 16561a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String encodeTuneParams(Bundle tuneParams) { 16571a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 16581a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Set<String> keySet = tuneParams.keySet(); 16591a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Iterator<String> it = keySet.iterator(); 16601a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim while (it.hasNext()) { 16611a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim String key = it.next(); 16621a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Object value = tuneParams.get(key); 16631a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (value == null) { 16641a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim continue; 16651a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 16661a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(key)); 16671a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append("="); 16681a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(value.toString())); 16691a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (it.hasNext()) { 16701a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(", "); 16711a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 16721a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 16731a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 16741a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 16751a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 16761a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String replaceEscapeCharacters(String src) { 16771a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final char ESCAPE_CHARACTER = '%'; 16781a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final String ENCODING_TARGET_CHARACTERS = "%=,"; 16791a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 16801a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim for (char ch : src.toCharArray()) { 16811a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (ENCODING_TARGET_CHARACTERS.indexOf(ch) >= 0) { 16821a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ESCAPE_CHARACTER); 16831a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 16841a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ch); 16851a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 16861a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 16871a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 16883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1690969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1691969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1692969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1693969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1694969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1695969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1696969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1697969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1698969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1699969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1700969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1701969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1702969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 17033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1704969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1705969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 17063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1707969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1708969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 17095c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 17105c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // A set of all TV content rating system xml uris. 17115c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>(); 17125c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 171372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 171472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 171572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 171672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1718187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1719187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 17203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 17223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 17233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1724969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1725969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1726969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1727969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 172879124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 17294c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // The token of a "main" TV input session. 17304c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private IBinder mainSessionToken = null; 1731783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1732783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // Persistent data store for all internal settings maintained by the TV input manager 1733783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // service. 1734783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private final PersistentDataStore persistentDataStore; 1735783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1736783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private UserState(Context context, int userId) { 1737783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo persistentDataStore = new PersistentDataStore(context, userId); 1738783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 17393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 174172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 174272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 174372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 174472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 174572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 174672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 174772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 174872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 174972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 175072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 175172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 175272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 1753a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee return mSessionTokens.isEmpty(); 175472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 175572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 175672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 175772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 175872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 175972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 176072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1761a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee // removed in releaseSessionLocked(). 176272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 176372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 176472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 176572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 176672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 176772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 176872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 176972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 177072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 177172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 177272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 177372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 177572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); 1776d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1777d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 17789e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 1779187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final boolean mIsHardware; 1780187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>(); 17813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1782d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1783d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1784d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 17852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 17863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17879e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState(ComponentName component, int userId) { 17889e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 17899e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mConnection = new InputServiceConnection(component, userId); 17909e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mComponent); 17913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1795187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final TvInputInfo mInfo; 1796d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1797d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1798d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 17992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 180072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1801d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1802d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 1803bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Not null if this session represents an external device connected to a hardware TV input. 1804bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private IBinder mHardwareSessionToken; 18053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1806bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client, 1807bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang int seq, int callingUid, int userId) { 180872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 1809187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mInfo = info; 18102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 18112b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 18122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 18132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 18142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 18162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 18172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 18182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 18192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 18202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 18212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 18222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 18232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 18242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 18252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 1827bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // If there are any other sessions based on this session, they should be released. 1828bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang UserState userState = getUserStateLocked(mUserId); 1829bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1830bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (mSession != null && mSession == sessionState.mHardwareSessionToken) { 1831bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1832bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mSession.release(); 1833bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1834bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in release", e); 1835bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1836bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1837bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mClient.onSessionReleased(sessionState.mSeq); 1838bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1839bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in onSessionReleased", e); 1840bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1841bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1842bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 184372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 18442b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 18499e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 18503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 18513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18529e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private InputServiceConnection(ComponentName component, int userId) { 18539e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 18553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 18589e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceConnected(ComponentName component, IBinder service) { 18593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 18609e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceConnected(component=" + component + ")"); 18613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1863969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 18649e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 1865d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 18663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1868187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 18699e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState.mCallback = new ServiceCallback(mComponent, mUserId); 18703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1871d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 18723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 18739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 18743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1878d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1879d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 18803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1881969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1882187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 18839e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component) 1884187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 18858e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1886187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1887187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1888187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1889187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1890187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 18914f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 18924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1893187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1894187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1895187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1896187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1897187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1898187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1899187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1900187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 19014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<HdmiCecDeviceInfo> cecDeviceInfoList = 19024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHdmiCecInputDeviceList(); 19034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (HdmiCecDeviceInfo cecDeviceInfo : cecDeviceInfoList) { 19044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 19054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 19064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 19074f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 19084f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19094f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1910969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 19113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19159e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceDisconnected(ComponentName component) { 19163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 19179e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceDisconnected(component=" + component + ")"); 19183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19199e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (!mComponent.equals(component)) { 19202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 19219e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee + mComponent + " (expected), " + component + " (actual)."); 19222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 19242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 19259e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 19262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 19272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 19282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 19292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 19302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 19312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 19322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 19332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 19342b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 19352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 19362b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 19372b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 1938187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 19392b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19402b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19412b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1942187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19439e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component)) { 1944bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1945187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 1946187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1947187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 19489e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(mComponent, mUserId); 19492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19502b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 19559e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 19563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 19573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19589e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceCallback(ComponentName component, int userId) { 19599e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 19603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 19613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19634f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 19644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 19654f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 19664f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 19674f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19684f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19694f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19704f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 19719e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputInfo.getId() == null || !mComponent.equals(inputInfo.getComponent())) { 19724f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 19734f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19744f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19754f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19764f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 19779e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 19784f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 19794f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 19804f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19814f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19834f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 19844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19854f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 1986187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 19874f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 19884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 19894f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19904f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1991187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 19924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 19934f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHdmiCecTvInput(int logicalAddress, TvInputInfo inputInfo) { 19944f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19954f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 19964f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 19974f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHdmiCecTvInput(logicalAddress, inputInfo); 19984f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 19993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2000187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2001187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2002187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2003187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 20044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 20069e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 2007187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 2008187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 2009187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 2010187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 2011187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 2012187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 2013187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 2014187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2015187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2016187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 2017187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 20184f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 2019187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2020187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 2021187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 20223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 202531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 202631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final class LogHandler extends Handler { 202731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_OPEN_ENTRY = 1; 202831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_UPDATE_ENTRY = 2; 202931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_CLOSE_ENTRY = 3; 203031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 203131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public LogHandler(Looper looper) { 203231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 203331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 203431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 203531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 203631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 203731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 203831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_OPEN_ENTRY: { 203931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 204031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 204131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 204231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 204331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 204431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 204531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 204631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 204731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_UPDATE_ENTRY: { 204831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 204931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 205031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 205131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 205231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onUpdateEntry(uri, channelId, time); 205331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 205431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 205531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 205631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_CLOSE_ENTRY: { 205731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 205831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 205931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg2; 206031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onCloseEntry(uri, time); 206131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 206231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 206331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 206431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 20656a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 206631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 206731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 206831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 206931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 207131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onOpenEntry(Uri uri, long channelId, long watchStarttime) { 207231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 2073f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_TITLE, 2074f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, 2075f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, 2076bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcbJae Seo TvContract.Programs.COLUMN_SHORT_DESCRIPTION 207731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2078f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " 2079f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND " 2080f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + ">?"; 208131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] selectionArgs = { 208231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(channelId), 208331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime), 208431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime) 208531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2086f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String sortOrder = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + " ASC"; 208731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 208831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 208931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection, 209031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo selection, selectionArgs, sortOrder); 209131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 209231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2093f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, cursor.getString(0)); 2094f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 2095f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo cursor.getLong(1)); 209631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(2); 2097f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 2098f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3)); 209931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 210031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 210131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Schedule an update when the current program ends. 210231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 210331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg1 = uri; 210431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = channelId; 210531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = endTime; 210631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args); 210731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo sendMessageDelayed(msg, endTime - System.currentTimeMillis()); 210831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 211031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 211131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 211231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 211331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 211431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 211531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 211631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onUpdateEntry(Uri uri, long channelId, long time) { 211731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 2118f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 2119f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 2120f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_TITLE, 2121f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 2122f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, 2123f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_DESCRIPTION 212431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 212531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 212631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 212731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(uri, projection, null, null, null); 212831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 212931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchStartTime = cursor.getLong(0); 213031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchEndTime = cursor.getLong(1); 213131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String title = cursor.getString(2); 213231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long startTime = cursor.getLong(3); 213331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(4); 213431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String description = cursor.getString(5); 213531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 213631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Do nothing if the current log entry is already closed. 213731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (watchEndTime > 0) { 213831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 213931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 214031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 214131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // The current program has just ended. Create a (complete) log entry off the 214231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // current entry. 214331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2144f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 214531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo watchStartTime); 2146f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, time); 2147f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 2148f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, title); 2149f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, startTime); 2150f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 2151f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, description); 215231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 215331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 215431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 215531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 215631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 215731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 215831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 215931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Re-open the current log entry with the next program information. 216031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 216131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 216331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onCloseEntry(Uri uri, long watchEndTime) { 216431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2165f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime); 216631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 216731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 216831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2169969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2170187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 2171187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2172187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 2173969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2174969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 2175969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2176969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2177187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2178187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2179187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 2180187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2181187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2182187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2183187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2184187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2185187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 2186187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 2187187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2188187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 2189187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2190187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2191187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2192187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2193187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2194187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 21954f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 2196187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2197187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2198187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2199187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2200187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2201187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 22024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 2203187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2204187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 2205187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2206187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2207187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2208187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2209187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2210187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 22114f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDeviceInfo) { 2212187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 22134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 22144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 22154f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 22164f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 22174f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 22184f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 22194f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 22204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 22214f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 22224f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2223187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2224187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2225187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2226187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 22274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDeviceInfo) { 2228187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 22294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 22304f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 22314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 22324f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 22334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 22344f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceRemoved(cecDeviceInfo); 22354f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 22364f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceRemoved", e); 22374f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 22384f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2239187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2240187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2241969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 22423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 2243