TvInputManagerService.java revision 426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9
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; 20e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; 21969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED; 22969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.app.ActivityManager; 243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.BroadcastReceiver; 253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ComponentName; 265c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderOperation; 275c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderResult; 2831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentResolver; 2931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentUris; 3031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentValues; 313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Context; 323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Intent; 333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.IntentFilter; 345c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.OperationApplicationException; 353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ServiceConnection; 363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.PackageManager; 373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ResolveInfo; 383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ServiceInfo; 399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.graphics.Rect; 40e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kimimport android.hardware.hdmi.HdmiControlManager; 4161f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jangimport android.hardware.hdmi.HdmiDeviceInfo; 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; 55d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputService; 56c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heoimport android.media.tv.TvStreamConfig; 571f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport android.media.tv.TvTrackInfo; 583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.net.Uri; 593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Binder; 60832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 6131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Handler; 623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.IBinder; 6331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Looper; 6431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Message; 653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Process; 663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.RemoteException; 673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.UserHandle; 689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Slog; 693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.util.SparseArray; 706a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputChannel; 713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.view.Surface; 723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.internal.content.PackageMonitor; 7431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.internal.os.SomeArgs; 75e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport com.android.internal.util.IndentingPrintWriter; 7631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.server.IoThread; 773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.server.SystemService; 783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 79e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport org.xmlpull.v1.XmlPullParserException; 80e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee 81e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.FileDescriptor; 82e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport java.io.IOException; 83e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.PrintWriter; 843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.ArrayList; 853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.HashMap; 865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.HashSet; 87187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport java.util.Iterator; 883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.List; 893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.Map; 905c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.Set; 913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/** This class provides a system service that manages television inputs. */ 933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopublic final class TvInputManagerService extends SystemService { 943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // STOPSHIP: Turn debugging off. 953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final boolean DEBUG = true; 963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final String TAG = "TvInputManagerService"; 973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Context mContext; 99c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareManager mTvInputHardwareManager; 1003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final ContentResolver mContentResolver; 10231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A global lock. 1043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Object mLock = new Object(); 1053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // ID of the current user. 1073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int mCurrentUserId = UserHandle.USER_OWNER; 1083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A map from user id to UserState. 1103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 1113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1127eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private final WatchLogHandler mWatchLogHandler; 11331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 1197eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mWatchLogHandler = new WatchLogHandler(IoThread.get().getLooper()); 12031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 121187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); 12231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 124783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo mUserStates.put(mCurrentUserId, new UserState(mContext, mCurrentUserId)); 1253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onStart() { 1303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo publishBinderService(Context.TV_INPUT_SERVICE, new BinderService()); 1313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1330ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee @Override 1340ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee public void onBootPhase(int phase) { 1350ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1360ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee registerBroadcastReceivers(); 137187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { 1380ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee synchronized (mLock) { 1390ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee buildTvInputListLocked(mCurrentUserId); 1400ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1410ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 142969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.onBootPhase(phase); 1430ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1440ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee 1453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void registerBroadcastReceivers() { 1463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageMonitor monitor = new PackageMonitor() { 1473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSomePackagesChanged() { 149426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang if (DEBUG) Slog.d(TAG, "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 userState.packageSet.clear(); 2193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (DEBUG) Slog.d(TAG, "buildTvInputList"); 2213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageManager pm = mContext.getPackageManager(); 2223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo List<ResolveInfo> services = pm.queryIntentServices( 223e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee new Intent(TvInputService.SERVICE_INTERFACE), 224e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 2254f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 2263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ResolveInfo ri : services) { 2273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ServiceInfo si = ri.serviceInfo; 2283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { 2299a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission " 2303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + android.Manifest.permission.BIND_TV_INPUT); 2313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo continue; 2323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2339cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo 2349cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo ComponentName component = new ComponentName(si.packageName, si.name); 2359cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (hasHardwarePermission(pm, component)) { 2369cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo ServiceState serviceState = userState.serviceStateMap.get(component); 2379cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (serviceState == null) { 2389cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // We see this hardware TV input service for the first time; we need to 2399cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // prepare the ServiceState object so that we can connect to the service and 2409cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // let it add TvInputInfo objects to mInputList if there's any. 2419cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo serviceState = new ServiceState(component, userId); 2429cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo userState.serviceStateMap.put(component, serviceState); 243187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2449cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo inputList.addAll(serviceState.mInputList); 245187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2469cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } else { 2479cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo try { 2489cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); 2499cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } catch (XmlPullParserException | IOException e) { 2509cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo Slog.e(TAG, "Failed to load TV input " + si.name, e); 2519cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo continue; 252969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2539cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } 254226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 2559cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo // Reconnect the service if existing input is updated. 2569cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo updateServiceConnectionLocked(component, userId); 2579cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo userState.packageSet.add(si.packageName); 2589cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo } 259187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2609cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 2619cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo for (TvInputInfo info : inputList) { 2629cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (DEBUG) Slog.d(TAG, "add " + info.getId()); 2639cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo TvInputState state = userState.inputMap.get(info.getId()); 2649cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo if (state == null) { 2659cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo state = new TvInputState(); 266e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 2679cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo state.mInfo = info; 2689cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo inputMap.put(info.getId(), state); 2693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : inputMap.keySet()) { 2728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!userState.inputMap.containsKey(inputId)) { 2738e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputAddedLocked(userState, inputId); 2748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2768e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2778e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (String inputId : userState.inputMap.keySet()) { 2788e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (!inputMap.containsKey(inputId)) { 279426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang TvInputInfo info = userState.inputMap.get(inputId).mInfo; 280426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 281426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang if (serviceState != null) { 282426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang abortPendingCreateSessionRequestsLocked(serviceState, inputId, userId); 283426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang } 2848e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputRemovedLocked(userState, inputId); 2858e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2868e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2878e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2888e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap.clear(); 2898e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap = inputMap; 2905c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 2915c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.clear(); 2925c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim for (TvInputState state : userState.inputMap.values()) { 2935c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri(); 2945c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim if (ratingSystemXmlUri != null) { 2955c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // TODO: need to check the validation of xml format and the duplication of rating 2965c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // systems. 2975c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(state.mInfo.getRatingSystemXmlUri()); 2985c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2995c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 3043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 3053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 3083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 3103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 313783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState = new UserState(mContext, userId); 3143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 3173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 3213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 322b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 323b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 324b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 325b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 3263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 3273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 328d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 3293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 330d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 3313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3329a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 3333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 3373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 3393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 340d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 3413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 342d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 3433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3449a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 3453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 347d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 3483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 3503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 35172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 35272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 3533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 3543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3659e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState getServiceStateLocked(ComponentName component, int userId) { 3663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3679e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 3683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 3699e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee throw new IllegalStateException("Service state not found for " + component + " (userId=" 3707de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3752b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 382d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3904c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return getSessionLocked(getSessionStateLocked(sessionToken, callingUid, userId)); 3914c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 3924c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 3934c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private ITvInputSession getSessionLocked(SessionState sessionState) { 394d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3964c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee throw new IllegalStateException("Session not yet created for token " 3974c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee + sessionState.mSessionToken); 3983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 4003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 4023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 4033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 4043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 4053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 4063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 408187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean shouldMaintainConnection(ServiceState serviceState) { 4099cc28e5175e1391646b29469d329c9c1c9311ee1Jae Seo return !serviceState.mSessionTokens.isEmpty() || serviceState.mIsHardware; 410187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // TODO: Find a way to maintain connection only when necessary. 411187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 412187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 4139e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private void updateServiceConnectionLocked(ComponentName component, int userId) { 4143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 4159e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 4163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 4173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting) { 4202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!serviceState.mSessionTokens.isEmpty()) { 4212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // wait until all the sessions are removed. 4222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 4232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 4242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = false; 4252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 426187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean maintainConnection = shouldMaintainConnection(serviceState); 427187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mService == null && maintainConnection && userId == mCurrentUserId) { 4283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is not yet connected but its state indicates that we 4293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // have pending requests. Then, connect the service. 430d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mBound) { 4313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // We have already bound to the service so we don't try to bind again until after we 4323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // unbind later on. 4333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 4343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4369e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "bindServiceAsUser(service=" + component + ", userId=" + userId + ")"); 4373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 438d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim 4399e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component); 440226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Binding service may fail if the service is updating. 441226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // In that case, the connection will be revived in buildTvInputListLocked called by 442226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // onSomePackagesChanged. 443e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee serviceState.mBound = mContext.bindServiceAsUser( 444e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); 445187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else if (serviceState.mService != null && !maintainConnection) { 4463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is already connected but its state indicates that we have 4473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // nothing to do with it. Then, disconnect the service. 4483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 4499e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "unbindService(service=" + component + ")"); 4503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 451d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 4529e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee userState.serviceStateMap.remove(component); 4533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 456426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang private void abortPendingCreateSessionRequestsLocked(ServiceState serviceState, 457426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang String inputId, int userId) { 458426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang // Let clients know the create session requests are failed. 459426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang UserState userState = getUserStateLocked(userId); 460426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang for (IBinder sessionToken : serviceState.mSessionTokens) { 461426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang SessionState sessionState = userState.sessionStateMap.get(sessionToken); 462426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang if (sessionState.mSession == null && (inputId == null 463426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang || sessionState.mInfo.getId().equals(inputId))) { 464426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang removeSessionStateLocked(sessionToken, sessionState.mUserId); 465426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang sendSessionTokenToClientLocked(sessionState.mClient, 466426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang sessionState.mInfo.getId(), null, null, sessionState.mSeq); 467426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang } 468426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang } 469426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang updateServiceConnectionLocked(serviceState.mComponent, userId); 470426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang } 471426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang 47272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 47372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 47472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 47572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 47672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 47772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 47872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 47972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 48072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 48172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 48272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 48372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4857de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 48672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 48772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 489187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")"); 4903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4916a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4926a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4936a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 497bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) { 4983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 499187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")"); 5003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 502d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 503bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken = harewareSessionToken; 504fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 505fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 506187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 507187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 508fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 5092b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 5102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 5112b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 5122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 5132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 51472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 51572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 51672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 51772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 51872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 51972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 52072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 52172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 522187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 523187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), sessionToken, channels[0], 524187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mSeq); 525fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 5266a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 5273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 529832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 530832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 5311f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 532a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 533a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5341f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 535a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 536a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 537a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 538a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 539a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5401f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 5411f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 5421f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 5431f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 5441f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 545a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5461f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 547a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 548a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 549a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 550a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 551a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 55210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTracksChanged(List<TvTrackInfo> tracks) { 553a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 554a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 55510d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTracksChanged(" + tracks + ")"); 556a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 557a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 558a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 559a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 560a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 56110d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTracksChanged(tracks, sessionState.mSeq); 562a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 56310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTracksChanged"); 564b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 565b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 566b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 567b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 568b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 56910d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTrackSelected(int type, String trackId) { 570d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo synchronized (mLock) { 571d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (DEBUG) { 57210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")"); 573d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 574d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 575d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo return; 576d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 577d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo try { 57810d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTrackSelected(type, trackId, sessionState.mSeq); 579d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } catch (RemoteException e) { 58010d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTrackSelected"); 581d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 582d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 583d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 584d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 585d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo @Override 5869b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 5879b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5889b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5899b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 5909b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5919b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5929b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5939b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5949b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5959b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 5969b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5979b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5989b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5999b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6009b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6019b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 6029b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 6039b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 6049b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 6059b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 6069b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 6079b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6089b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 6099b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 6109b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6119b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 6129b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 6139b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 6149b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 6159b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6169b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6179b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6189b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 6199b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 620bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed() { 621bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo synchronized (mLock) { 622bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 623bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.d(TAG, "onContentAllowed()"); 624bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 625bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 626bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo return; 627bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 628bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo try { 629bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo sessionState.mClient.onContentAllowed(sessionState.mSeq); 630bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } catch (RemoteException e) { 631bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.e(TAG, "error in onContentAllowed"); 632bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 633bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 634bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 635bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 636bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 6376057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String rating) { 6386057102dbb746593a7d59cf377c969b62e38c664Jae Seo synchronized (mLock) { 6396057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (DEBUG) { 6406057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.d(TAG, "onContentBlocked()"); 6416057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6426057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 6436057102dbb746593a7d59cf377c969b62e38c664Jae Seo return; 6446057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6456057102dbb746593a7d59cf377c969b62e38c664Jae Seo try { 6466057102dbb746593a7d59cf377c969b62e38c664Jae Seo sessionState.mClient.onContentBlocked(rating, sessionState.mSeq); 6476057102dbb746593a7d59cf377c969b62e38c664Jae Seo } catch (RemoteException e) { 6486057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.e(TAG, "error in onContentBlocked"); 6496057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6506057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6516057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6526057102dbb746593a7d59cf377c969b62e38c664Jae Seo 6536057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 654ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho public void onLayoutSurface(int left, int top, int right, int bottom) { 655ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho synchronized (mLock) { 656ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (DEBUG) { 657ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top 658ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho + ", right=" + right + ", bottom=" + bottom + ",)"); 659ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 660ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 661ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho return; 662ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 663ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho try { 664ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mClient.onLayoutSurface(left, top, right, bottom, 665ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mSeq); 666ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } catch (RemoteException e) { 667ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.e(TAG, "error in onLayoutSurface"); 668ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 669ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 670ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 671ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho 672ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho @Override 673832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 674832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 675832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 676832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 677832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 678832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 679832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 680832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 681832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 682832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 683832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 684832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 685832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 686832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 687832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 688832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 6893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 6903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 6923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 693187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim service.createSession(channels[1], callback, sessionState.mInfo.getId()); 6943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 6959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 696fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 697187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null, 698187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim null, sessionState.mSeq); 6993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7006a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 7013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 703d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 7045c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 7053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 706d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 7073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 7089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 7093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7102b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 7122b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 7132b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 7142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 71515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee UserState userState = getUserStateLocked(userId); 71615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 71715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee setMainLocked(sessionToken, false, callingUid, userId); 71815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 7192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 7202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 7212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 7222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 7232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 7253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 7273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 729fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 730fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 731abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 73215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 73315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "mainSessionToken=null"); 73415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 735abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken = null; 736abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 737abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 738abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee // Remove the session state from the global session state map of the current user. 739fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 740fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 7418d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee if (sessionState == null) { 7428d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee return; 7438d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee } 7448d4ded0058de5c573ccf79c4596bf5eb1b14fad3Chulwoo Lee 74572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 74672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 74772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 74872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 74972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 75072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 75172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 75272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 75372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 75472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 755187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 756187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 757187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 758187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 759187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 760187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 761fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 762187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 7637eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 7647eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // Log the end of watch. 7657eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo SomeArgs args = SomeArgs.obtain(); 7667eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg1 = sessionToken; 7677eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg2 = System.currentTimeMillis(); 7687eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_END, args).sendToTarget(); 769fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 770fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 77115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee private void setMainLocked(IBinder sessionToken, boolean isMain, int callingUid, int userId) { 77215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 77315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (sessionState.mHardwareSessionToken != null) { 77415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee sessionState = getSessionStateLocked(sessionState.mHardwareSessionToken, 77515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Process.SYSTEM_UID, userId); 77615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 77715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee ServiceState serviceState = getServiceStateLocked(sessionState.mInfo.getComponent(), 77815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee userId); 77915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (!serviceState.mIsHardware) { 78015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee return; 78115c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 78215c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee ITvInputSession session = getSessionLocked(sessionState); 78315c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee try { 78415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee session.setMain(isMain); 78515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } catch (RemoteException e) { 78615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.e(TAG, "error in setMain", e); 78715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 78815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 78915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee 7908e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7918e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7928e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7938e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7948e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7958e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7968e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7978e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7988e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7998e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 8008e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 8018e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 8028e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 8038e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 8048e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 8058e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 8068e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 8078e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 8088e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 8098e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 8108e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 8118e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 8128e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 8138e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 8148e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 8158e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 8168e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 817969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 818969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 8198e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 820969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 821969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 822969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 823969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 824969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 825969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 826969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 827969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 828969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 829969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 830969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 8312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 832969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 8332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 834969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 8352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8362b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8372b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 8382b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 839969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 840969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 841969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 842c88f1916b8ab7f5f75a00375c6fb4873ea5044afJi-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(inputState.mInfo.getComponent()); 843969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 844969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 845187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 846187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 847969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 848969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 849969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 850969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 8518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 852969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 853969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 854969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 8553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 8563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 8583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 8603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 864969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 865969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 866969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 868969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 873b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 874b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 875b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 876b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 877b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 878b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 879b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 880b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 881b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 882b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 883b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 884b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 885b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 886b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 887b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 888b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8925c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim public List<Uri> getTvContentRatingSystemXmls(int userId) { 8935c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8945c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls"); 8955c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final long identity = Binder.clearCallingIdentity(); 8965c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim try { 8975c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim synchronized (mLock) { 8985c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim UserState userState = getUserStateLocked(resolvedUserId); 8995c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>(); 9005c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet); 9015c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim return ratingSystemXmlUriList; 9025c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 9035c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } finally { 9045c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.restoreCallingIdentity(identity); 9055c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 9065c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 9075c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 9085c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim @Override 909969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 9103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 9113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 9123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 9153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 916969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 917969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 9188e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 919969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 9203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 928969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 9293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 9303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 9313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 9323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 9333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 934969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 935969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 9363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 943783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isParentalControlsEnabled(int userId) { 944783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 945783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isParentalControlsEnabled"); 946783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 947783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 948783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 949783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 950783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isParentalControlsEnabled(); 951783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 952783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 953783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 954783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 955783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 956783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 957783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 958783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void setParentalControlsEnabled(boolean enabled, int userId) { 959783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 960783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 961783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "setParentalControlsEnabled"); 962783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 963783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 964783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 965783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 966783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.setParentalControlsEnabled(enabled); 967783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 968783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 969783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 970783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 971783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 972783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 973783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 974783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isRatingBlocked(String rating, int userId) { 975783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 976783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isRatingBlocked"); 977783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 978783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 979783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 980783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 981783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isRatingBlocked( 982783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 983783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 984783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 985783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 986783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 987783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 988783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 989783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 990783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public List<String> getBlockedRatings(int userId) { 991783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 992783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "getBlockedRatings"); 993783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 994783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 995783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 996783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 997783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo List<String> ratings = new ArrayList<String>(); 998783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo for (TvContentRating rating 999783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo : userState.persistentDataStore.getBlockedRatings()) { 1000783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ratings.add(rating.flattenToString()); 1001783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1002783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return ratings; 1003783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1004783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 1005783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 1006783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1007783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1008783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1009783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1010783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void addBlockedRating(String rating, int userId) { 1011783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 1012783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 1013783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "addBlockedRating"); 1014783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 1015783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 1016783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 1017783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 1018783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.addBlockedRating( 1019783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 1020783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1021783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 1022783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 1023783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1024783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1025783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1026783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1027783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void removeBlockedRating(String rating, int userId) { 1028783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 1029783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 1030783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "removeBlockedRating"); 1031783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 1032783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 1033783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 1034783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 1035783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.removeBlockedRating( 1036783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 1037783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1038783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 1039783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 1040783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1041783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1042783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1043783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private void ensureParentalControlsPermission() { 1044550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // STOPSHIP: Uncomment when b/16984416 is resolved. 1045550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo //if (mContext.checkCallingPermission( 1046550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) 1047550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // != PackageManager.PERMISSION_GRANTED) { 1048550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // throw new SecurityException( 1049550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo // "The caller does not have parental controls permission"); 1050550c4b0d4dc6f3e2ef388b4250c758829c8255bcJae Seo //} 1051783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1052783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1053783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1054d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 10553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 10563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 10593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 1063426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang TvInputState inputState = userState.inputMap.get(inputId); 1064426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang if (inputState == null) { 1065426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang Slog.w(TAG, "Failed to find input state for inputId=" + inputId); 1066426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang sendSessionTokenToClientLocked(client, inputId, null, null, seq); 1067426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang return; 1068426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang } 1069426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang TvInputInfo info = inputState.mInfo; 1070187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 10713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 1072187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 1073187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 10743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10752b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 10762b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 10775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 10782b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 10792b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 10802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10812b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 10822b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 1083187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 108472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 10852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 10872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 10882b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 1090d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 10913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1092d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 1093d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 10947de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 10953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 1096187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 10973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 11003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 11053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 110615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 110715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "releaseSession(): " + sessionToken); 110815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 11093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 11123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 11163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 11183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 11234c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void setMainSession(IBinder sessionToken, int userId) { 112415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 112515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "setMainSession(): " + sessionToken); 112615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee } 11274c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int callingUid = Binder.getCallingUid(); 11284c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11294c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userId, "setMainSession"); 11304c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final long identity = Binder.clearCallingIdentity(); 11314c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 11324c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (mLock) { 1133982abe693f66037ca265b88057eceb5a3e815182Ji-Hwan Lee UserState userState = getUserStateLocked(resolvedUserId); 1134956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (userState.mainSessionToken == sessionToken) { 11354c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return; 11364c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 113715c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (DEBUG) { 113815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee Slog.d(TAG, "mainSessionToken=" + sessionToken); 1139abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 114015c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee IBinder oldMainSessionToken = userState.mainSessionToken; 11414c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userState.mainSessionToken = sessionToken; 11424c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1143956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // Inform the new main session first. 114415c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee // See {@link TvInputService.Session#onSetMain}. 114515c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (sessionToken != null) { 114615c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee setMainLocked(sessionToken, true, callingUid, userId); 11474c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 114815c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee if (oldMainSessionToken != null) { 114915c56aac985bc8d75f38fb4ecb92dda12d2ca06cJi-Hwan Lee setMainLocked(oldMainSessionToken, false, Process.SYSTEM_UID, userId); 11504c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11514c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11524c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } finally { 11534c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Binder.restoreCallingIdentity(identity); 11544c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11554c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11564c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 11574c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 11583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 11593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 11623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1166bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1167bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1168bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken == null) { 1169bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setSurface(surface); 1170bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } else { 1171bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1172bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setSurface(surface); 1173bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 11743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 11759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 11763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 1179f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 1180f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 1181f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 1182f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 11833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1188e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 1189e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 1190e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 1191e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1192e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 1193e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 1194e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1195e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 1196e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1197bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1198bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1199bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).dispatchSurfaceChanged(format, width, height); 1200bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1201bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, Process.SYSTEM_UID, 1202bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId).dispatchSurfaceChanged(format, width, height); 1203bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1204e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 1205e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 1206e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1207e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1208e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 1209e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 1210e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1211e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1212e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 1213e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 12143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 1215bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_ON = 1.0f; 1216bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_OFF = 0f; 12173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 12183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 12203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 12213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 12233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1224bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1225bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1226bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setVolume(volume); 1227bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1228bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Here, we let the hardware session know only whether volume is on or 1229bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // off to prevent that the volume is controlled in the both side. 1230bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1231bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f) 1232bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF); 1233bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 12343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12359a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 12363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 12433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 12441a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) { 12453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 12463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 12483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 12493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 12513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12521a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( 12531a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim channelUri, params); 1254c22d0c0941ab65ca69977d002c4431394a735c7dJae Seo if (TvContract.isChannelUriForPassthroughInput(channelUri)) { 1255008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 1256008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 1257008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 125831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 125931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 126031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 126131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 12627eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // Log the start of watch. 126331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 12647eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg1 = sessionState.mInfo.getComponent().getPackageName(); 12657eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg2 = System.currentTimeMillis(); 12667eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg3 = ContentUris.parseId(channelUri); 12677eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg4 = params; 12687eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo args.arg5 = sessionToken; 12697eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_START, args) 12707eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo .sendToTarget(); 12713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 12733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 12743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12829bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 12839bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1284903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1285903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1286903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1287903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1288903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1289903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1290903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1291903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 12929bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1293903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1294903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1295903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1296903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1297903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1298903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1299903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1300903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1301903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1302903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 13032c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 13042c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 13052c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13062c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 13072c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 13082c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13092c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 13102c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13112c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 13122c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 13132c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 13142c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 13152c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13162c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13172c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 13182c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 13192c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13202c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13212c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 13222c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 132310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void selectTrack(IBinder sessionToken, int type, String trackId, int userId) { 13241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 13251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 13271f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 13281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13291f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 13301f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13311f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 133210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo type, trackId); 13331f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 13341f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 13351f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13361f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13371f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 13381f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 13391f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13401f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13411f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 13421f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1343a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1344a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1345a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1346a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1347a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1348a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1349a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1350a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1351a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1352a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1353a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1354a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1355a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1356a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1357a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1358a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1359a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1360a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1361a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1362a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1363a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 13649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 13659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 13669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 13699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 13759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 13779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 13869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 13899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 13959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 13979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 14009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 14019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14029a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14039a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 14049a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 14059a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 14069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 14079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 14089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 14099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 14109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 14129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 14149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 14159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 14169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 14179a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14189a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14199a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 14209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 14219a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14229a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1423c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1424c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1425c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1426969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1427c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1428c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1429c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1430c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1431c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1432c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1433c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1434c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1435c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1436c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1437c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1438c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1439c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1440c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1441969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1442969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1443969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1444c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1445c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1446c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1447c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1448c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1449c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1450c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1451c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1452c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1453c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1454969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1455c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1456c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1457c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1458c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1459c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1460c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1461c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1462c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1463969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1464c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1465c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1466c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1467c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1468c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1469c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1470c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1471c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1472c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1473c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1474c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1475c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1476c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1477c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1478c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1479e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1480e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 1481c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) 1482c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1483c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1484c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1485c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1486c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1487c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1488c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1489c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1490c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1491c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1492c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "getAvailableTvStreamConfigList"); 1493c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1494c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.getAvailableTvStreamConfigList( 1495c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo inputId, callingUid, resolvedUserId); 1496c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1497c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1498c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1499c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1500c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1501c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1502c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config, 1503c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int userId) 1504c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1505c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1506c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1507c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1508c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1509c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1510c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1511c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1512c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1513c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1514c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "captureFrame"); 1515c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1516bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang String hardwareInputId = null; 151779124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 151879124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1519bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (userState.inputMap.get(inputId) == null) { 1520bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "Input not found for " + inputId); 1521bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang return false; 1522bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1523bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1524bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mInfo.getId().equals(inputId) 1525bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang && sessionState.mHardwareSessionToken != null) { 1526bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang hardwareInputId = userState.sessionStateMap.get( 1527bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken).mInfo.getId(); 1528bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang break; 1529bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1530bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 153179124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 1532c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.captureFrame( 1533bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang (hardwareInputId != null) ? hardwareInputId : inputId, 153479124a717c09f12c74d587d3977bf33ca37e6420Terry Heo surface, config, callingUid, resolvedUserId); 1535c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1536c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1537c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1538c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1539c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1540c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1541df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo public boolean isSingleSessionActive(int userId) throws RemoteException { 1542df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final long identity = Binder.clearCallingIdentity(); 1543df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int callingUid = Binder.getCallingUid(); 1544df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1545df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo userId, "isSingleSessionActive"); 1546df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo try { 1547df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo synchronized (mLock) { 1548df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1549df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (userState.sessionStateMap.size() == 1) { 1550df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1551df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1552df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo else if (userState.sessionStateMap.size() == 2) { 1553df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo SessionState[] sessionStates = userState.sessionStateMap.values().toArray( 1554df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo new SessionState[0]); 1555df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo // Check if there is a wrapper input. 1556df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (sessionStates[0].mHardwareSessionToken != null 1557df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo || sessionStates[1].mHardwareSessionToken != null) { 1558df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1559df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1560df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1561df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return false; 1562df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1563df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } finally { 1564df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo Binder.restoreCallingIdentity(identity); 1565df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1566df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1567df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo 1568df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo @Override 15690f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1570e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1571e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 15720f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1573e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 15740f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 15750f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1576e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1577e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1578e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1579e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1580e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1581e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1582e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1583e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1584e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1585e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1586e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1587e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1588e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1589e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1590e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1591e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1592e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1593e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1594969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1595e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 15968e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 15978e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1598e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1599e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1600e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1601969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1602e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1603969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1604e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1605e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1606e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1607e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1608e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1609e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1610e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1611e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1612e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1613e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1614e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1615e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1616e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1617e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1618e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1619e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1620e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1621e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1622e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1623e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1624e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1625e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1626e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1627e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1628e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1629e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1630e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1631187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1632e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1633187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1634e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1635e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1636e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1637e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1638e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1639e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1640e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1641e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1642e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1643e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1644e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1645e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1646e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1647e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1648e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1649e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1650e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1651e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1652e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1653e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1654e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1655e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1656e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1657e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1658e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1659e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1660e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1661e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1662e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1663e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1664187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1665e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1666e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1667e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1668e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1669e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1670e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1671e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1672bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang pw.println("mHardwareSessionToken: " + session.mHardwareSessionToken); 1673e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1674e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1675e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1676e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1677969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1678969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1679969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1680969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1681969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1682969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1683969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1684956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee pw.println("mainSessionToken: " + userState.mainSessionToken); 1685e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1686e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1687e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1688e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 16893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 16903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1691969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1692969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1693969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1694969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1695969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1696969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1697969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1698969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1699969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1700969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1701969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1702969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1703969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 17043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1705969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1706969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 17073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1708969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1709969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 17105c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 17115c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // A set of all TV content rating system xml uris. 17125c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>(); 17135c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 171472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 171572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 171672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 171772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1719187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1720187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 17213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 17233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 17243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1725969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1726969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1727969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1728969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 172979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 17304c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // The token of a "main" TV input session. 17314c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private IBinder mainSessionToken = null; 1732783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1733783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // Persistent data store for all internal settings maintained by the TV input manager 1734783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // service. 1735783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private final PersistentDataStore persistentDataStore; 1736783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1737783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private UserState(Context context, int userId) { 1738783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo persistentDataStore = new PersistentDataStore(context, userId); 1739783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 17403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 174272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 174372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 174472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 174572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 174672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 174772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 174872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 174972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 175072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 175172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 175272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 175372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 1754a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee return mSessionTokens.isEmpty(); 175572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 175672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 175772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 175872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 175972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 176072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 176172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1762a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee // removed in releaseSessionLocked(). 176372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 176472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 176572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 176672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 176772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 176872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 176972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 177072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 177172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 177272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 177372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 177472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 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()) { 18300c38fc764b0e1c5c8b880872d9b4a647a76955cdJi-Hwan Lee if (mSessionToken == sessionState.mHardwareSessionToken) { 18314835497886ee876b16e1144d32f5bdcfbb7e9062Ji-Hwan Lee releaseSessionLocked(sessionState.mSessionToken, Process.SYSTEM_UID, 18324835497886ee876b16e1144d32f5bdcfbb7e9062Ji-Hwan Lee mUserId); 1833bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1834bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mClient.onSessionReleased(sessionState.mSeq); 1835bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1836bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in onSessionReleased", e); 1837bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1838bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1839bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 184072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 18412b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 18469e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 18473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 18483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18499e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private InputServiceConnection(ComponentName component, int userId) { 18509e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 18523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 18559e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceConnected(ComponentName component, IBinder service) { 18563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 18579e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceConnected(component=" + component + ")"); 18583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1860969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 18619e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 1862d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 18633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1865187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 18669e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState.mCallback = new ServiceCallback(mComponent, mUserId); 18673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1868d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 18693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 18709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 18713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1875d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1876d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 18773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1878969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1879187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 18809e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component) 1881187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 18828e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1883187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1884187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1885187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1886187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1887187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 18884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 18894f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1890187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1891187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1892187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1893187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1894187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1895187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1896187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1897187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1898546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo List<HdmiDeviceInfo> deviceInfoList = 1899546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mTvInputHardwareManager.getHdmiDeviceList(); 1900546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo for (HdmiDeviceInfo deviceInfo : deviceInfoList) { 19014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 1902546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 19034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 1904546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 19054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1907969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 19083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19129e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceDisconnected(ComponentName component) { 19133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 19149e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceDisconnected(component=" + component + ")"); 19153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19169e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (!mComponent.equals(component)) { 19172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 19189e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee + mComponent + " (expected), " + component + " (actual)."); 19192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 19212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 19229e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 19232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 19242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 19252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 19262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 19272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 19282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1929426c9a4008b75b93cbfea15aa4b8c47c5fdb49b9Dongwon Kang abortPendingCreateSessionRequestsLocked(serviceState, null, mUserId); 19302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1931187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19329e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component)) { 1933bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1934187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 1935187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1936187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 19372b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19382b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 19439e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 19443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 19453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19469e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceCallback(ComponentName component, int userId) { 19479e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 19483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 19493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19514f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 19524f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 19534f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 19544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 19554f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19564f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 19599e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputInfo.getId() == null || !mComponent.equals(inputInfo.getComponent())) { 19604f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 19614f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19634f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 19659e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 19664f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 19674f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 19684f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19694f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 19703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19714f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 19724f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19734f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 1974187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 19754f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 19764f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 19774f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19784f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1979187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 19804f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 19818960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim public void addHdmiTvInput(int id, TvInputInfo inputInfo) { 19824f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19834f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 19844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 19858960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim mTvInputHardwareManager.addHdmiTvInput(id, inputInfo); 19864f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 19873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1988187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1989187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1990187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 1991187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 19924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 19933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 19949e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 1995187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 1996187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 1997187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 1998187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 1999187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 2000187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 2001187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 2002187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2003187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2004187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 2005187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 20064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 2007187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2008187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 2009187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 20103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 201331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 20147eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private final class WatchLogHandler extends Handler { 20157eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // There are only two kinds of watch events that can happen on the system: 20167eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // 1. The current TV input session is tuned to a new channel. 20177eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // 2. The session is released for some reason. 20187eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // The former indicates the end of the previous log entry, if any, followed by the start of 20197eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // a new entry. The latter indicates the end of the most recent entry for the given session. 20207eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // Here the system supplies the database the smallest set of information only that is 20217eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // sufficient to consolidate the log entries while minimizing database operations in the 20227eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo // system service. 20237eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private static final int MSG_LOG_WATCH_START = 1; 20247eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private static final int MSG_LOG_WATCH_END = 2; 20257eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20267eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo public WatchLogHandler(Looper looper) { 202731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 202831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 202931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 203031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 203131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 203231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 20337eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo case MSG_LOG_WATCH_START: { 203431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 20357eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo String packageName = (String) args.arg1; 20367eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo long watchStartTime = (long) args.arg2; 20377eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo long channelId = (long) args.arg3; 20387eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Bundle tuneParams = (Bundle) args.arg4; 20397eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo IBinder sessionToken = (IBinder) args.arg5; 20407eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20417eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo ContentValues values = new ContentValues(); 20427eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 20437eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 20447eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo watchStartTime); 20457eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 20467eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (tuneParams != null) { 20477eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_INTERNAL_TUNE_PARAMS, 20487eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo encodeTuneParams(tuneParams)); 20497eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo } 20507eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_INTERNAL_SESSION_TOKEN, 20517eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo sessionToken.toString()); 20527eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20537eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 205431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 205531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 205631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 20577eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo case MSG_LOG_WATCH_END: { 205831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 20597eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo IBinder sessionToken = (IBinder) args.arg1; 20607eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo long watchEndTime = (long) args.arg2; 20617eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20627eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo ContentValues values = new ContentValues(); 20637eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 20647eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo watchEndTime); 20657eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_INTERNAL_SESSION_TOKEN, 20667eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo sessionToken.toString()); 20677eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo 20687eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 206931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 207031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 207131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 20736a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 207431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 207531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 20797eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private String encodeTuneParams(Bundle tuneParams) { 20807eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo StringBuilder builder = new StringBuilder(); 20817eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Set<String> keySet = tuneParams.keySet(); 20827eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Iterator<String> it = keySet.iterator(); 20837eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo while (it.hasNext()) { 20847eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo String key = it.next(); 20857eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo Object value = tuneParams.get(key); 20867eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (value == null) { 20877eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo continue; 208831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 20897eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(replaceEscapeCharacters(key)); 20907eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append("="); 20917eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(replaceEscapeCharacters(value.toString())); 20927eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (it.hasNext()) { 20937eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(", "); 209431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 209531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 20967eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo return builder.toString(); 209731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 209831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 20997eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo private String replaceEscapeCharacters(String src) { 21007eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo final char ESCAPE_CHARACTER = '%'; 21017eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo final String ENCODING_TARGET_CHARACTERS = "%=,"; 21027eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo StringBuilder builder = new StringBuilder(); 21037eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo for (char ch : src.toCharArray()) { 21047eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo if (ENCODING_TARGET_CHARACTERS.indexOf(ch) >= 0) { 21057eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(ESCAPE_CHARACTER); 2106579befecb248162021929ab58ffd23f1724cc6beJae Seo } 21077eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo builder.append(ch); 2108579befecb248162021929ab58ffd23f1724cc6beJae Seo } 21097eb75dff7a0fb4b19c3e801cd388483d7d471f41Jae Seo return builder.toString(); 2110579befecb248162021929ab58ffd23f1724cc6beJae Seo } 211131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2112969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2113187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 2114187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2115187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 2116969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2117969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 2118969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2119969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2120187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2121187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2122187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 2123187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2124187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2125187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2126187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2127187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2128187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 2129187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 2130187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2131187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 2132187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2133187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2134187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2135187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2136187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2137187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 21384f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 2139187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2140187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2141187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2142187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2143187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2144187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 21454f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 2146187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2147187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 2148187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2149187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2150187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2151187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2152187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2153187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2154546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceAdded(HdmiDeviceInfo deviceInfo) { 2155187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 21564f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 21574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 21584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 21594f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 21604f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2161546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceAdded(deviceInfo); 21624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2163546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); 21644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 21654f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2166187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2167187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2168187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2169187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2170546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) { 2171187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 21724f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 21734f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 21744f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 21754f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 21764f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 2177546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo serviceState.mService.notifyHdmiDeviceRemoved(deviceInfo); 21784f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 2179546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e); 21804f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 21814f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2182187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2183187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 218461daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang 218561daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang @Override 2186e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo deviceInfo) { 2187e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim synchronized (mLock) { 2188e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim Integer state = null; 2189e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim switch (deviceInfo.getDevicePowerStatus()) { 2190e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_ON: 2191e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim state = INPUT_STATE_CONNECTED; 2192e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim break; 2193e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_STANDBY: 2194e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON: 2195e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY: 2196e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim state = INPUT_STATE_CONNECTED_STANDBY; 2197e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim break; 2198e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim case HdmiControlManager.POWER_STATUS_UNKNOWN: 2199e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim default: 2200e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim state = null; 2201e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim break; 2202e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim } 2203e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim if (state != null) { 2204e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim setStateLocked(inputId, state.intValue(), mCurrentUserId); 2205e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim } 2206e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim } 220761daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } 2208969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 22093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 2210