TvInputManagerService.java revision 956afc2ba79f50bb8025c6d334653e3c3419b480
13957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/* 23957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Copyright (C) 2014 The Android Open Source Project 33957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 43957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Licensed under the Apache License, Version 2.0 (the "License"); 53957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * you may not use this file except in compliance with the License. 63957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * You may obtain a copy of the License at 73957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 83957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * http://www.apache.org/licenses/LICENSE-2.0 93957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Unless required by applicable law or agreed to in writing, software 113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * distributed under the License is distributed on an "AS IS" BASIS, 123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * See the License for the specific language governing permissions and 143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * limitations under the License. 153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo */ 163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopackage com.android.server.tv; 183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; 20969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED; 21969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.app.ActivityManager; 233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.BroadcastReceiver; 243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ComponentName; 255c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderOperation; 265c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderResult; 2731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentResolver; 2831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentUris; 2931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentValues; 303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Context; 313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Intent; 323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.IntentFilter; 335c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.OperationApplicationException; 343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ServiceConnection; 353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.PackageManager; 363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ResolveInfo; 373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ServiceInfo; 385c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Limimport android.content.res.Resources; 3931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.database.Cursor; 409a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.graphics.Rect; 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 11231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final Handler mLogHandler; 11331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 11931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler = new LogHandler(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() { 1493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(mCurrentUserId); 1513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1535c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo @Override 1555c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo public void onPackageRemoved(String packageName, int uid) { 1565c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo synchronized (mLock) { 1575c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo UserState userState = getUserStateLocked(mCurrentUserId); 158969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (!userState.packageSet.contains(packageName)) { 1595c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo // Not a TV input package. 1605c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo return; 1615c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1625c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1635c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1645c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ArrayList<ContentProviderOperation> operations = 1655c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo new ArrayList<ContentProviderOperation>(); 1665c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1675c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; 1685c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String[] selectionArgs = { packageName }; 1695c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1705c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI) 1715c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI) 1735c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1745c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation 1755c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .newDelete(TvContract.WatchedPrograms.CONTENT_URI) 1765c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ContentProviderResult[] results = null; 1795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo try { 1805c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations); 1815c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } catch (RemoteException | OperationApplicationException e) { 1825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.e(TAG, "error in applyBatch" + e); 1835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo if (DEBUG) { 1865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid 1875c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo + ")"); 1885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "results=" + results); 1895c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1905c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 1923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo monitor.register(mContext, null, UserHandle.ALL, true); 1933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo IntentFilter intentFilter = new IntentFilter(); 1953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 1963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext.registerReceiverAsUser(new BroadcastReceiver() { 1983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onReceive(Context context, Intent intent) { 2003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String action = intent.getAction(); 2013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (Intent.ACTION_USER_SWITCHED.equals(action)) { 2023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 2043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 2053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }, UserHandle.ALL, intentFilter, null, null); 2083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2109e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private static boolean hasHardwarePermission(PackageManager pm, ComponentName component) { 211187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, 2129e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee component.getPackageName()) == PackageManager.PERMISSION_GRANTED; 213187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 214187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void buildTvInputListLocked(int userId) { 2163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 217969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2188e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 219969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.packageSet.clear(); 2203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2219a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (DEBUG) Slog.d(TAG, "buildTvInputList"); 2223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageManager pm = mContext.getPackageManager(); 2233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo List<ResolveInfo> services = pm.queryIntentServices( 224e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee new Intent(TvInputService.SERVICE_INTERFACE), 225e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 2264f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 2273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ResolveInfo ri : services) { 2283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ServiceInfo si = ri.serviceInfo; 2293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { 2309a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission " 2313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + android.Manifest.permission.BIND_TV_INPUT); 2323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo continue; 2333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 234e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee try { 2354f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.clear(); 2369e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ComponentName component = new ComponentName(si.packageName, si.name); 2379e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (hasHardwarePermission(pm, component)) { 2389e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 239187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState == null) { 240187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // We see this hardware TV input service for the first time; we need to 241187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // prepare the ServiceState object so that we can connect to the service and 242187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // let it add TvInputInfo objects to mInputList if there's any. 2439e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState = new ServiceState(component, userId); 2449e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee userState.serviceStateMap.put(component, serviceState); 245187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2464f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.addAll(serviceState.mInputList); 247187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 248187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2494f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee inputList.add(TvInputInfo.createTvInputInfo(mContext, ri)); 250187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 251187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2524f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (TvInputInfo info : inputList) { 253187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (DEBUG) Slog.d(TAG, "add " + info.getId()); 2548e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim TvInputState state = userState.inputMap.get(info.getId()); 255187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (state == null) { 256187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state = new TvInputState(); 257187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 258187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim state.mInfo = info; 2598e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim inputMap.put(info.getId(), state); 260969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 261226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 262226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Reconnect the service if existing input is updated. 2639e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(component, userId); 264187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 265187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.packageSet.add(si.packageName); 266e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } catch (IOException | XmlPullParserException e) { 267e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee Slog.e(TAG, "Can't load TV input " + si.name, e); 268e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 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)) { 2798e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputRemovedLocked(userState, inputId); 2808e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2818e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 2828e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 2838e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap.clear(); 2848e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim userState.inputMap = inputMap; 2855c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 2865c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Resources r = Resources.getSystem(); 2875c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.clear(); 2885c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(TvContentRating.SYSTEM_CONTENT_RATING_SYSTEM_XML); 2895c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim for (TvInputState state : userState.inputMap.values()) { 2905c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Uri ratingSystemXmlUri = state.mInfo.getRatingSystemXmlUri(); 2915c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim if (ratingSystemXmlUri != null) { 2925c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // TODO: need to check the validation of xml format and the duplication of rating 2935c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // systems. 2945c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim userState.ratingSystemXmlUriSet.add(state.mInfo.getRatingSystemXmlUri()); 2955c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2965c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 2973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 3053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 3063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 3073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 310783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState = new UserState(mContext, userId); 3113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 3133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 3143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 3183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 319b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 320b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 321b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 322b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 3233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 3243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 325d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 3263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 327d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 3283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3299a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 3303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 3343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 3363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 337d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 3383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 339d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 3403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 3419a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 3423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 34472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.clear(); 345d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 3463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 3483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 34972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 35072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 3513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 3523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3639e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState getServiceStateLocked(ComponentName component, int userId) { 3643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3659e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(component); 3663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 3679e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee throw new IllegalStateException("Service state not found for " + component + " (userId=" 3687de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 380d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3842b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3884c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return getSessionLocked(getSessionStateLocked(sessionToken, callingUid, userId)); 3894c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 3904c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 3914c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private ITvInputSession getSessionLocked(SessionState sessionState) { 392d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3944c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee throw new IllegalStateException("Session not yet created for token " 3954c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee + sessionState.mSessionToken); 3963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 3983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 4003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 4013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 4023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 4033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 4043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 406187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static boolean shouldMaintainConnection(ServiceState serviceState) { 407187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim return !serviceState.mClientTokens.isEmpty() 408187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || !serviceState.mSessionTokens.isEmpty() 409187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim || 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 45672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 45772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 45872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 45972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 46072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 46172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 46272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 46372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 46472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 46572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 46672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 46772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4697de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 47072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 47172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 473187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInfo.getId() + ")"); 4743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4756a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4766a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4776a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 481bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) { 4823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 483187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInfo.getId() + ")"); 4843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 486d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 487bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken = harewareSessionToken; 488fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 489fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 490187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 491187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 492fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 4932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 4942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 4952b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 4962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 4972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 49872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 49972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 50072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 50172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 50272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 50372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 50472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 50572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 506187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, 507187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), sessionToken, channels[0], 508187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mSeq); 509fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 5106a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 5113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 513832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 514832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 5151f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 516a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 517a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 5181f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 519a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 520a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 521a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 522a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 523a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 5241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 5251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 5261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 5271f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 5281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 529a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 5301f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 531a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 532a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 533a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 534a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 535a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 53610d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTracksChanged(List<TvTrackInfo> tracks) { 537a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 538a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 53910d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTracksChanged(" + tracks + ")"); 540a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 541a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 542a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 543a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 544a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 54510d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTracksChanged(tracks, sessionState.mSeq); 546a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 54710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTracksChanged"); 548b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 549b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 550b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 551b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 552b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 55310d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void onTrackSelected(int type, String trackId) { 554d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo synchronized (mLock) { 555d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (DEBUG) { 55610d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.d(TAG, "onTrackSelected(type=" + type + ", trackId=" + trackId + ")"); 557d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 558d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 559d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo return; 560d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 561d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo try { 56210d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo sessionState.mClient.onTrackSelected(type, trackId, sessionState.mSeq); 563d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } catch (RemoteException e) { 56410d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo Slog.e(TAG, "error in onTrackSelected"); 565d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 566d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 567d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo } 568d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo 569d5ce9759524740cfb02638fd1d7b44315957b422Jae Seo @Override 5709b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 5719b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5729b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5739b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 5749b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5759b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5769b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5779b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5789b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5799b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 5809b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5819b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5829b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5839b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5849b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5859b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5869b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 5879b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 5889b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5899b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5909b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 5919b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5929b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5939b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5949b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5959b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5969b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 5979b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5989b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 5999b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6009b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6019b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 6029b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 6039b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 604bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo public void onContentAllowed() { 605bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo synchronized (mLock) { 606bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (DEBUG) { 607bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.d(TAG, "onContentAllowed()"); 608bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 609bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 610bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo return; 611bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 612bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo try { 613bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo sessionState.mClient.onContentAllowed(sessionState.mSeq); 614bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } catch (RemoteException e) { 615bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo Slog.e(TAG, "error in onContentAllowed"); 616bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 617bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 618bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo } 619bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo 620bbcd206a798c8c2845200daf7a2d4cb7b29056f3Jae Seo @Override 6216057102dbb746593a7d59cf377c969b62e38c664Jae Seo public void onContentBlocked(String rating) { 6226057102dbb746593a7d59cf377c969b62e38c664Jae Seo synchronized (mLock) { 6236057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (DEBUG) { 6246057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.d(TAG, "onContentBlocked()"); 6256057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6266057102dbb746593a7d59cf377c969b62e38c664Jae Seo if (sessionState.mSession == null || sessionState.mClient == null) { 6276057102dbb746593a7d59cf377c969b62e38c664Jae Seo return; 6286057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6296057102dbb746593a7d59cf377c969b62e38c664Jae Seo try { 6306057102dbb746593a7d59cf377c969b62e38c664Jae Seo sessionState.mClient.onContentBlocked(rating, sessionState.mSeq); 6316057102dbb746593a7d59cf377c969b62e38c664Jae Seo } catch (RemoteException e) { 6326057102dbb746593a7d59cf377c969b62e38c664Jae Seo Slog.e(TAG, "error in onContentBlocked"); 6336057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6346057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6356057102dbb746593a7d59cf377c969b62e38c664Jae Seo } 6366057102dbb746593a7d59cf377c969b62e38c664Jae Seo 6376057102dbb746593a7d59cf377c969b62e38c664Jae Seo @Override 638ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho public void onLayoutSurface(int left, int top, int right, int bottom) { 639ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho synchronized (mLock) { 640ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (DEBUG) { 641ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top 642ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho + ", right=" + right + ", bottom=" + bottom + ",)"); 643ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 644ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 645ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho return; 646ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 647ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho try { 648ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mClient.onLayoutSurface(left, top, right, bottom, 649ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho sessionState.mSeq); 650ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } catch (RemoteException e) { 651ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho Slog.e(TAG, "error in onLayoutSurface"); 652ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 653ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 654ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho } 655ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho 656ff04ae757a5542d2d5633e75b7adacc4fce1ce7eYoungsang Cho @Override 657832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 658832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 659832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 660832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 661832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 662832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 663832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 664832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 665832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 666832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 667832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 668832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 669832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 670832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 671832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 672832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 6733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 6743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 6763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 677187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim service.createSession(channels[1], callback, sessionState.mInfo.getId()); 6783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 6799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 680fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 681187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInfo.getId(), null, 682187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim null, sessionState.mSeq); 6833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6846a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 6853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 687d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 6885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 6893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 690d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 6913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 6929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 6933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 6962b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 6972b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 6982b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 6992b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 7002b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 7012b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 7022b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 7032b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7042b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 7053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7062b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 7073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 709fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 710fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 711abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (sessionToken == userState.mainSessionToken) { 712abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken = null; 713abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 714abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 715abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee // Remove the session state from the global session state map of the current user. 716fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 717fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 71831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry, if any. 719d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 72031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 721d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 72231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = System.currentTimeMillis(); 72331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget(); 72431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 72531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 72672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 72772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 72872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 72972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 73072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 73172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 73272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 73372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 73572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 736187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = sessionState.mInfo; 737187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (info != null) { 738187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 739187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null) { 740187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mSessionTokens.remove(sessionToken); 741187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 742fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 743187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(sessionState.mInfo.getComponent(), userId); 744fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 745fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 7468e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputAddedLocked(UserState userState, String inputId) { 7478e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7488e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputAdded: inputId = " + inputId); 7498e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7508e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7518e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7528e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputAdded(inputId); 7538e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7548e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report added input to callback."); 7558e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7568e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7578e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7588e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7598e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputRemovedLocked(UserState userState, String inputId) { 7608e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim if (DEBUG) { 7618e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputRemovedLocked: inputId = " + inputId); 7628e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7638e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 7648e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim try { 7658e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim callback.onInputRemoved(inputId); 7668e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } catch (RemoteException e) { 7678e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.e(TAG, "Failed to report removed input to callback."); 7688e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7698e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7708e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim } 7718e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim 7728e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim private void notifyInputStateChangedLocked(UserState userState, String inputId, 773969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 774969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 7758e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim Slog.d(TAG, "notifyInputStateChangedLocked: inputId = " + inputId 776969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 777969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 778969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 779969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 780969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 781969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 782969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 783969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 784969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 785969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 786969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 7872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 788969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 7892b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 790969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 7912b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7922b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7932b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7942b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 795969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 796969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 797969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 798c88f1916b8ab7f5f75a00375c6fb4873ea5044afJi-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(inputState.mInfo.getComponent()); 799969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 800969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 801187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState != null && serviceState.mService == null 802187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && shouldMaintainConnection(serviceState)) { 803969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 804969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 805969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 806969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 8078e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputId, state, null); 808969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 809969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 810969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 8113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 8123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 8143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 8163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 820969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 821969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 822969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 8233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 824969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 8253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 829b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 830b375805f3b1672e68d1511565af4700e5fa8491dJae Seo 831b375805f3b1672e68d1511565af4700e5fa8491dJae Seo @Override 832b375805f3b1672e68d1511565af4700e5fa8491dJae Seo public TvInputInfo getTvInputInfo(String inputId, int userId) { 833b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 834b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.getCallingUid(), userId, "getTvInputInfo"); 835b375805f3b1672e68d1511565af4700e5fa8491dJae Seo final long identity = Binder.clearCallingIdentity(); 836b375805f3b1672e68d1511565af4700e5fa8491dJae Seo try { 837b375805f3b1672e68d1511565af4700e5fa8491dJae Seo synchronized (mLock) { 838b375805f3b1672e68d1511565af4700e5fa8491dJae Seo UserState userState = getUserStateLocked(resolvedUserId); 839b375805f3b1672e68d1511565af4700e5fa8491dJae Seo TvInputState state = userState.inputMap.get(inputId); 840b375805f3b1672e68d1511565af4700e5fa8491dJae Seo return state == null ? null : state.mInfo; 841b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 842b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } finally { 843b375805f3b1672e68d1511565af4700e5fa8491dJae Seo Binder.restoreCallingIdentity(identity); 844b375805f3b1672e68d1511565af4700e5fa8491dJae Seo } 8453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8485c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim public List<Uri> getTvContentRatingSystemXmls(int userId) { 8495c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8505c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.getCallingUid(), userId, "getTvContentRatingSystemXmls"); 8515c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim final long identity = Binder.clearCallingIdentity(); 8525c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim try { 8535c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim synchronized (mLock) { 8545c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim UserState userState = getUserStateLocked(resolvedUserId); 8555c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim List<Uri> ratingSystemXmlUriList = new ArrayList<Uri>(); 8565c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim ratingSystemXmlUriList.addAll(userState.ratingSystemXmlUriSet); 8575c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim return ratingSystemXmlUriList; 8585c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8595c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } finally { 8605c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim Binder.restoreCallingIdentity(identity); 8615c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8625c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim } 8635c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 8645c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim @Override 865969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 8663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 8683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 872969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 873969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 8748e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, state.mInfo.getId(), 875969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 8763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 884969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 8853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 8863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 8873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 890969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 891969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 8923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 899783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isParentalControlsEnabled(int userId) { 900783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 901783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isParentalControlsEnabled"); 902783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 903783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 904783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 905783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 906783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isParentalControlsEnabled(); 907783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 908783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 909783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 910783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 911783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 912783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 913783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 914783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void setParentalControlsEnabled(boolean enabled, int userId) { 915783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 916783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 917783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "setParentalControlsEnabled"); 918783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 919783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 920783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 921783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 922783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.setParentalControlsEnabled(enabled); 923783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 924783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 925783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 926783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 927783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 928783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 929783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 930783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public boolean isRatingBlocked(String rating, int userId) { 931783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 932783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "isRatingBlocked"); 933783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 934783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 935783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 936783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 937783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return userState.persistentDataStore.isRatingBlocked( 938783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 939783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 940783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 941783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 942783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 943783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 944783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 945783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 946783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public List<String> getBlockedRatings(int userId) { 947783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 948783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "getBlockedRatings"); 949783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 950783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 951783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 952783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 953783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo List<String> ratings = new ArrayList<String>(); 954783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo for (TvContentRating rating 955783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo : userState.persistentDataStore.getBlockedRatings()) { 956783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ratings.add(rating.flattenToString()); 957783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 958783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo return ratings; 959783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 960783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 961783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 962783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 963783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 964783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 965783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 966783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void addBlockedRating(String rating, int userId) { 967783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 968783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 969783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "addBlockedRating"); 970783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 971783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 972783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 973783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 974783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.addBlockedRating( 975783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 976783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 977783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 978783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 979783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 980783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 981783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 982783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 983783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo public void removeBlockedRating(String rating, int userId) { 984783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo ensureParentalControlsPermission(); 985783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 986783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.getCallingUid(), userId, "removeBlockedRating"); 987783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo final long identity = Binder.clearCallingIdentity(); 988783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo try { 989783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo synchronized (mLock) { 990783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 991783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo userState.persistentDataStore.removeBlockedRating( 992783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo TvContentRating.unflattenFromString(rating)); 993783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 994783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } finally { 995783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo Binder.restoreCallingIdentity(identity); 996783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 997783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 998783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 999783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private void ensureParentalControlsPermission() { 1000783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo if (mContext.checkCallingPermission( 1001783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) 1002783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo != PackageManager.PERMISSION_GRANTED) { 1003783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo throw new SecurityException( 1004783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo "The caller does not have parental controls permission"); 1005783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1006783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 1007783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1008783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo @Override 1009d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 10103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 10113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 10143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 1018187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputInfo info = userState.inputMap.get(inputId).mInfo; 1019187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(info.getComponent()); 10203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 1021187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState = new ServiceState(info.getComponent(), resolvedUserId); 1022187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim userState.serviceStateMap.put(info.getComponent(), serviceState); 10233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 10252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 10265c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 10272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 10282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 10292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 10312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 1032187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim SessionState sessionState = new SessionState(sessionToken, info, client, 103372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 10342b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 10362b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 10372b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 10382b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 1039d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 10403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1041d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 1042d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 10437de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 10443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 1045187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim updateServiceConnectionLocked(info.getComponent(), resolvedUserId); 10463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 10553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 10563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 10583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 10593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 10603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 10612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 10623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 10643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 10653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 10673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 10694c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee public void setMainSession(IBinder sessionToken, int userId) { 10704c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int callingUid = Binder.getCallingUid(); 10714c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10724c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userId, "setMainSession"); 10734c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee final long identity = Binder.clearCallingIdentity(); 10744c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 10754c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee synchronized (mLock) { 1076982abe693f66037ca265b88057eceb5a3e815182Ji-Hwan Lee UserState userState = getUserStateLocked(resolvedUserId); 1077956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (userState.mainSessionToken == sessionToken) { 10784c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee return; 10794c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 10804c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1081956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee SessionState newMainSessionState = getSessionStateLocked( 1082956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee sessionToken, callingUid, resolvedUserId); 1083956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (newMainSessionState.mHardwareSessionToken != null) { 1084956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState = getSessionStateLocked( 1085956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState.mHardwareSessionToken, 1086956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee Process.SYSTEM_UID, resolvedUserId); 1087956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee } 1088956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ServiceState newMainServiceState = getServiceStateLocked( 1089956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSessionState.mInfo.getComponent(), resolvedUserId); 1090956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ITvInputSession newMainSession = getSessionLocked(newMainSessionState); 10914c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1092956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ServiceState oldMainServiceState = null; 1093956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee ITvInputSession oldMainSession = null; 1094abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee if (userState.mainSessionToken != null) { 1095956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee SessionState oldMainSessionState = getSessionStateLocked( 1096abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId); 1097956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (oldMainSessionState.mHardwareSessionToken != null) { 1098956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState = getSessionStateLocked( 1099956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState.mHardwareSessionToken, 1100956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee Process.SYSTEM_UID, resolvedUserId); 1101956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee } 1102956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainServiceState = getServiceStateLocked( 1103956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSessionState.mInfo.getComponent(), resolvedUserId); 1104956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSession = getSessionLocked(oldMainSessionState); 1105abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee } 1106abca0ee7949f59e72b8d2764dafa23af18eb51dbJi-Hwan Lee 11074c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee userState.mainSessionToken = sessionToken; 11084c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 1109956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // Inform the new main session first. 1110956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee // See {@link TvInputService#onSetMainSession}. 1111956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (newMainServiceState.mIsHardware) { 11124c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 1113956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee newMainSession.setMainSession(true); 11144c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 11154c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 11164c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11174c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 1118956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee if (oldMainSession != null && oldMainServiceState.mIsHardware) { 11194c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee try { 1120956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee oldMainSession.setMainSession(false); 11214c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } catch (RemoteException e) { 11224c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Slog.e(TAG, "error in setMainSession", e); 11234c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11244c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11254c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11264c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } finally { 11274c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee Binder.restoreCallingIdentity(identity); 11284c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11294c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee } 11304c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee 11314c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee @Override 11323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 11333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 11363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1140bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1141bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1142bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken == null) { 1143bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setSurface(surface); 1144bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } else { 1145bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1146bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setSurface(surface); 1147bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 11483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 11499a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 11503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 1153f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 1154f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 1155f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 1156f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 11573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 11583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 11603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 11613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1162e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 1163e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 1164e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 1165e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1166e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 1167e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 1168e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1169e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 1170e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 1171bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1172bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1173bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).dispatchSurfaceChanged(format, width, height); 1174bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1175bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, Process.SYSTEM_UID, 1176bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId).dispatchSurfaceChanged(format, width, height); 1177bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1178e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 1179e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 1180e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1181e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1182e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 1183e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 1184e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1185e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 1186e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 1187e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 11883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 1189bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_ON = 1.0f; 1190bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang final float REMOTE_VOLUME_OFF = 0f; 11913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 11923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 11933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 11943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 11953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 11963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 11973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1198bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, 1199bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang resolvedUserId); 1200bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState).setVolume(volume); 1201bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mHardwareSessionToken != null) { 1202bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Here, we let the hardware session know only whether volume is on or 1203bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // off to prevent that the volume is controlled in the both side. 1204bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang getSessionLocked(sessionState.mHardwareSessionToken, 1205bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f) 1206bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF); 1207bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 12083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 12103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 12173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 12181a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) { 12193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 12203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 12213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 12223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 12233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 12253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 12261a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim getSessionLocked(sessionToken, callingUid, resolvedUserId).tune( 12271a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim channelUri, params); 1228008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho if (TvContract.isChannelUriForPassthroughTvInput(channelUri)) { 1229008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho // Do not log the watch history for passthrough inputs. 1230008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho return; 1231008f6d4e326f6372e165bdf342178ecd1e834e2fYoungsang Cho } 123231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long currentTime = System.currentTimeMillis(); 123331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = ContentUris.parseId(channelUri); 123431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 123531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry first, if any. 123631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 123731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 1238d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 123931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1240d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 124131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = currentTime; 124231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args) 124331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo .sendToTarget(); 124431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 124531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 124631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Create a log entry and fill it later. 1247187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim String packageName = sessionState.mInfo.getServiceInfo().packageName; 124831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 12495c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 1250f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 125131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo currentTime); 1252f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 1253f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 12541a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (params != null) { 12551a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim values.put(TvContract.WatchedPrograms.COLUMN_TUNE_PARAMS, 12561a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim encodeTuneParams(params)); 12571a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 125831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1259d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mLogUri = mContentResolver.insert( 126031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo TvContract.WatchedPrograms.CONTENT_URI, values); 126131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 1262d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 126331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = ContentUris.parseId(channelUri); 126431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = currentTime; 126531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget(); 12663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 12679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 12683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 12693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 12723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 12733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 12769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 12779bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim public void requestUnblockContent( 12789bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim IBinder sessionToken, String unblockedRating, int userId) { 1279903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int callingUid = Binder.getCallingUid(); 1280903d6b72cd572665309633e925485464d08bb25aJaewan Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1281903d6b72cd572665309633e925485464d08bb25aJaewan Kim userId, "unblockContent"); 1282903d6b72cd572665309633e925485464d08bb25aJaewan Kim final long identity = Binder.clearCallingIdentity(); 1283903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1284903d6b72cd572665309633e925485464d08bb25aJaewan Kim synchronized (mLock) { 1285903d6b72cd572665309633e925485464d08bb25aJaewan Kim try { 1286903d6b72cd572665309633e925485464d08bb25aJaewan Kim getSessionLocked(sessionToken, callingUid, resolvedUserId) 12879bf671f8ee72b156f16fcf05a3d1c6e093ecba67Sungsoo Lim .requestUnblockContent(unblockedRating); 1288903d6b72cd572665309633e925485464d08bb25aJaewan Kim } catch (RemoteException e) { 1289903d6b72cd572665309633e925485464d08bb25aJaewan Kim Slog.e(TAG, "error in unblockContent", e); 1290903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1291903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1292903d6b72cd572665309633e925485464d08bb25aJaewan Kim } finally { 1293903d6b72cd572665309633e925485464d08bb25aJaewan Kim Binder.restoreCallingIdentity(identity); 1294903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1295903d6b72cd572665309633e925485464d08bb25aJaewan Kim } 1296903d6b72cd572665309633e925485464d08bb25aJaewan Kim 1297903d6b72cd572665309633e925485464d08bb25aJaewan Kim @Override 12982c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 12992c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 13002c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13012c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 13022c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 13032c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13042c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 13052c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 13062c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 13072c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 13082c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 13092c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 13102c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13112c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13122c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 13132c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 13142c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13152c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 13162c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 13172c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 131810d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo public void selectTrack(IBinder sessionToken, int type, String trackId, int userId) { 13191f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 13201f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13211f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 13221f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 13231f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13241f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 13251f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 13261f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 132710d285ac06b3d3060c7d90d3dc196d4ac8367467Jae Seo type, trackId); 13281f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 13291f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 13301f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13311f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13321f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 13331f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 13341f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13351f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 13361f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 13371f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 1338a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, 1339a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo int userId) { 1340a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int callingUid = Binder.getCallingUid(); 1341a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1342a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo userId, "sendAppPrivateCommand"); 1343a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo final long identity = Binder.clearCallingIdentity(); 1344a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1345a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo synchronized (mLock) { 1346a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo try { 1347a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 1348a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo .appPrivateCommand(command, data); 1349a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } catch (RemoteException e) { 1350a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Slog.e(TAG, "error in sendAppPrivateCommand", e); 1351a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1352a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1353a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } finally { 1354a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo Binder.restoreCallingIdentity(identity); 1355a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1356a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo } 1357a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo 1358a759b111a1c9cb00284038f8a1554bf29709b952Jae Seo @Override 13599a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 13609a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 13619a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13629a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13639a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 13649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13659a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13669a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13679a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13689a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13699a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 13709a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13719a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 13729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 13809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 13819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 13829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 13839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 13849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 13859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 13879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 13889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 13899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 13909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 13919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 13929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 13959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 13969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 13989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 13999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 14009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 14019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 14029a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 14039a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 14049a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 14059a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 14079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 14089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 14099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 14109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 14119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 14129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 14159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 14169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 14179a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1418c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1419c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1420c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1421969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1422c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1423c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1424c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1425c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1426c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1427c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1428c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1429c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1430c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1431c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1432c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1433c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1434c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1435c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1436969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1437969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1438969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1439c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1440c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1441c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1442c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1443c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1444c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1445c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1446c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1447c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1448c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1449969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1450c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1451c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1452c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1453c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1454c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1455c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1456c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1457c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1458969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1459c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1460c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1461c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1462c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1463c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1464c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1465c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1466c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1467c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1468c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1469c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1470c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1471c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1472c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1473c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1474e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1475e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 1476c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId) 1477c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1478c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1479c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1480c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1481c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1482c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1483c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1484c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1485c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1486c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1487c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "getAvailableTvStreamConfigList"); 1488c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1489c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.getAvailableTvStreamConfigList( 1490c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo inputId, callingUid, resolvedUserId); 1491c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1492c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1493c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1494c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1495c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1496c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1497c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config, 1498c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int userId) 1499c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throws RemoteException { 1500c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mContext.checkCallingPermission( 1501c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo android.Manifest.permission.CAPTURE_TV_INPUT) 1502c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo != PackageManager.PERMISSION_GRANTED) { 1503c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo throw new SecurityException("Requires CAPTURE_TV_INPUT permission"); 1504c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1505c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1506c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final long identity = Binder.clearCallingIdentity(); 1507c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int callingUid = Binder.getCallingUid(); 1508c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1509c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo userId, "captureFrame"); 1510c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo try { 1511bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang String hardwareInputId = null; 151279124a717c09f12c74d587d3977bf33ca37e6420Terry Heo synchronized (mLock) { 151379124a717c09f12c74d587d3977bf33ca37e6420Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1514bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (userState.inputMap.get(inputId) == null) { 1515bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "Input not found for " + inputId); 1516bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang return false; 1517bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1518bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1519bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (sessionState.mInfo.getId().equals(inputId) 1520bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang && sessionState.mHardwareSessionToken != null) { 1521bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang hardwareInputId = userState.sessionStateMap.get( 1522bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mHardwareSessionToken).mInfo.getId(); 1523bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang break; 1524bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1525bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 152679124a717c09f12c74d587d3977bf33ca37e6420Terry Heo } 1527c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mTvInputHardwareManager.captureFrame( 1528bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang (hardwareInputId != null) ? hardwareInputId : inputId, 152979124a717c09f12c74d587d3977bf33ca37e6420Terry Heo surface, config, callingUid, resolvedUserId); 1530c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } finally { 1531c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Binder.restoreCallingIdentity(identity); 1532c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1533c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 1534c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 1535c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 1536df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo public boolean isSingleSessionActive(int userId) throws RemoteException { 1537df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final long identity = Binder.clearCallingIdentity(); 1538df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int callingUid = Binder.getCallingUid(); 1539df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1540df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo userId, "isSingleSessionActive"); 1541df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo try { 1542df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo synchronized (mLock) { 1543df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo UserState userState = getUserStateLocked(resolvedUserId); 1544df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (userState.sessionStateMap.size() == 1) { 1545df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1546df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1547df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo else if (userState.sessionStateMap.size() == 2) { 1548df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo SessionState[] sessionStates = userState.sessionStateMap.values().toArray( 1549df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo new SessionState[0]); 1550df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo // Check if there is a wrapper input. 1551df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo if (sessionStates[0].mHardwareSessionToken != null 1552df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo || sessionStates[1].mHardwareSessionToken != null) { 1553df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return true; 1554df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1555df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1556df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo return false; 1557df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1558df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } finally { 1559df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo Binder.restoreCallingIdentity(identity); 1560df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1561df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo } 1562df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo 1563df9f0a321e0cb2958c9d170395a0367a106fa0e6Terry Heo @Override 15640f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1565e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1566e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 15670f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1568e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 15690f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 15700f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1571e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1572e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1573e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1574e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1575e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1576e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1577e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1578e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1579e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1580e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1581e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1582e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1583e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1584e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1585e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1586e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1587e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1588e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1589969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1590e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 15918e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim for (Map.Entry<String, TvInputState> entry: userState.inputMap.entrySet()) { 15928e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim pw.println(entry.getKey() + ": " + entry.getValue()); 1593e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1594e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1595e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1596969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1597e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1598969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1599e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1600e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1601e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1602e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1603e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1604e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1605e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1606e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1607e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1608e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1609e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1610e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1611e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1612e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1613e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1614e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1615e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1616e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1617e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1618e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1619e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1620e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1621e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1622e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1623e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1624e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1625e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1626187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("serviceStateMap: ComponentName -> ServiceState"); 1627e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1628187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Map.Entry<ComponentName, ServiceState> entry : 1629e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1630e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1631e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1632e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1633e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1634e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1635e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens:"); 1636e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1637e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mClientTokens) { 1638e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1639e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1640e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1641e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1642e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1643e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1644e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1645e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1646e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1647e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1648e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1649e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1650e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1651e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1652e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1653e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1654e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1655e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1656e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1657e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1658e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1659e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1660e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1661e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1662e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1663e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1664e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1665e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1666187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim pw.println("mInfo: " + session.mInfo); 1667e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1668e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1669e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1670e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1671e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1672e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1673e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1674bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang pw.println("mHardwareSessionToken: " + session.mHardwareSessionToken); 1675e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1676e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1677e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1678e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1679969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1680969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1681969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1682969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1683969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1684969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1685969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1686956afc2ba79f50bb8025c6d334653e3c3419b480Ji-Hwan Lee pw.println("mainSessionToken: " + userState.mainSessionToken); 1687e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1688e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1689e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1690e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 16911a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 16921a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String encodeTuneParams(Bundle tuneParams) { 16931a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 16941a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Set<String> keySet = tuneParams.keySet(); 16951a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Iterator<String> it = keySet.iterator(); 16961a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim while (it.hasNext()) { 16971a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim String key = it.next(); 16981a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim Object value = tuneParams.get(key); 16991a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (value == null) { 17001a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim continue; 17011a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17021a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(key)); 17031a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append("="); 17041a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(replaceEscapeCharacters(value.toString())); 17051a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (it.hasNext()) { 17061a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(", "); 17071a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17081a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17091a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 17101a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17111a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim 17121a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim private String replaceEscapeCharacters(String src) { 17131a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final char ESCAPE_CHARACTER = '%'; 17141a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim final String ENCODING_TARGET_CHARACTERS = "%=,"; 17151a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim StringBuilder builder = new StringBuilder(); 17161a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim for (char ch : src.toCharArray()) { 17171a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim if (ENCODING_TARGET_CHARACTERS.indexOf(ch) >= 0) { 17181a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ESCAPE_CHARACTER); 17191a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17201a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim builder.append(ch); 17211a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17221a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim return builder.toString(); 17231a6b25eabcc1fb66e6e8d76f91fd413e18b793a9Sungsoo Lim } 17243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1726969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1727969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1728969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1729969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1730969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1731969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1732969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1733969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1734969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1735969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1736969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1737969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1738969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 17393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1740969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1741969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 17423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1743969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1744969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 17455c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 17465c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim // A set of all TV content rating system xml uris. 17475c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim private final Set<Uri> ratingSystemXmlUriSet = new HashSet<Uri>(); 17485c5b83fcd58d21c9ab7ac986bf84f604ec5bb4b5Sungsoo Lim 174972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 175072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 175172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 175272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 17533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1754187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Map<ComponentName, ServiceState> serviceStateMap = 1755187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim new HashMap<ComponentName, ServiceState>(); 17563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 17573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 17583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 17593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1760969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1761969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1762969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1763969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 176479124a717c09f12c74d587d3977bf33ca37e6420Terry Heo 17654c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee // The token of a "main" TV input session. 17664c52697dbed682a19dacc78b0c08931ea8dbc6b5Ji-Hwan Lee private IBinder mainSessionToken = null; 1767783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1768783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // Persistent data store for all internal settings maintained by the TV input manager 1769783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo // service. 1770783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private final PersistentDataStore persistentDataStore; 1771783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo 1772783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo private UserState(Context context, int userId) { 1773783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo persistentDataStore = new PersistentDataStore(context, userId); 1774783645e99f909ffc7a2d5d2fca9324cc0e9b7362Jae Seo } 17753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 17763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 177772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 177872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 177972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 178072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 178172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 178272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 178372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 178472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 178572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 178672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 178772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 178872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 1789a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee return mSessionTokens.isEmpty(); 179072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 179172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 179272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 179372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 179472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 179572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 179672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1797a65118e13b5ceb54454b48f67ea754a38a08f27aJi-Hwan Lee // removed in releaseSessionLocked(). 179872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 179972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 180072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 180172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 180272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 180372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 180672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 180972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 18103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 181172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); 1812d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1813d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 18149e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 1815187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final boolean mIsHardware; 1816187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final List<TvInputInfo> mInputList = new ArrayList<TvInputInfo>(); 18173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1818d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1819d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1820d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 18212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 18223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18239e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private ServiceState(ComponentName component, int userId) { 18249e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18259e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mConnection = new InputServiceConnection(component, userId); 18269e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mIsHardware = hasHardwarePermission(mContext.getPackageManager(), mComponent); 18273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1831187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final TvInputInfo mInfo; 1832d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1833d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1834d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 18352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 183672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1837d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1838d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 1839bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // Not null if this session represents an external device connected to a hardware TV input. 1840bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private IBinder mHardwareSessionToken; 18413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1842bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang private SessionState(IBinder sessionToken, TvInputInfo info, ITvInputClient client, 1843bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang int seq, int callingUid, int userId) { 184472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 1845187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mInfo = info; 18462b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 18472b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 18482b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 18492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 18502b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 18522b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 18532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 18542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 18552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 18562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 18572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 18582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 18592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 18602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 18612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 1863bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang // If there are any other sessions based on this session, they should be released. 1864bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang UserState userState = getUserStateLocked(mUserId); 1865bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang for (SessionState sessionState : userState.sessionStateMap.values()) { 1866bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang if (mSession != null && mSession == sessionState.mHardwareSessionToken) { 1867bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1868bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mSession.release(); 1869bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1870bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in release", e); 1871bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1872bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang try { 1873bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang sessionState.mClient.onSessionReleased(sessionState.mSeq); 1874bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } catch (RemoteException e) { 1875bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang Slog.e(TAG, "error in onSessionReleased", e); 1876bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1877bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 1878bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang } 187972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 18802b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 18813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 18859e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 18863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 18873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18889e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private InputServiceConnection(ComponentName component, int userId) { 18899e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 18903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 18913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 18933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 18949e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceConnected(ComponentName component, IBinder service) { 18953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 18969e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceConnected(component=" + component + ")"); 18973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 18983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1899969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 19009e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 1901d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 19023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 1904187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware && serviceState.mCallback == null) { 19059e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee serviceState.mCallback = new ServiceCallback(mComponent, mUserId); 19063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1907d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 19083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 19099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 19103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1914d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1915d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 19163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1917969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1918187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19199e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component) 1920187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim && inputState.mState != INPUT_STATE_DISCONNECTED) { 19218e6b51b0fb810ac990c863cc0579e2b2700ab7d6Jaewan Kim notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1922187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim inputState.mState, null); 1923187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1924187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1925187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 1926187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (serviceState.mIsHardware) { 19274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee List<TvInputHardwareInfo> hardwareInfoList = 19284f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHardwareList(); 1929187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputHardwareInfo hardwareInfo : hardwareInfoList) { 1930187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 1931187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(hardwareInfo); 1932187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 1933187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 1934187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1935187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1936187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 193761f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang List<HdmiDeviceInfo> cecDeviceInfoList = 19384f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.getHdmiCecInputDeviceList(); 193961f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang for (HdmiDeviceInfo cecDeviceInfo : cecDeviceInfoList) { 19404f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 19414f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 19424f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 19434f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 19444f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 19454f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 1946969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 19473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 19519e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee public void onServiceDisconnected(ComponentName component) { 19523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 19539e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee Slog.d(TAG, "onServiceDisconnected(component=" + component + ")"); 19543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19559e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (!mComponent.equals(component)) { 19562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 19579e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee + mComponent + " (expected), " + component + " (actual)."); 19582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 19602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 19619e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = userState.serviceStateMap.get(mComponent); 19622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 19632b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 19642b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 19652b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 19662b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 19672b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 19682b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 19692b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 19702b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 19712b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 19722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 19732b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 1974187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim sessionState.mInfo.getId(), null, null, sessionState.mSeq); 19752b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19762b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19772b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1978187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (TvInputState inputState : userState.inputMap.values()) { 19799e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputState.mInfo.getComponent().equals(component)) { 1980bd2fa2c02d916a9b6c62f8fd8701d779c00bd68dDongwon Kang notifyInputStateChangedLocked(userState, inputState.mInfo.getId(), 1981187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim INPUT_STATE_DISCONNECTED, null); 1982187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1983187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 19849e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee updateServiceConnectionLocked(mComponent, mUserId); 19852b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19862b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 19873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 19919e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee private final ComponentName mComponent; 19923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 19933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19949e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceCallback(ComponentName component, int userId) { 19959e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee mComponent = component; 19963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 19973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 19983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureHardwarePermission() { 20004f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 20014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee != PackageManager.PERMISSION_GRANTED) { 20024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new SecurityException("The caller does not have hardware permission"); 20034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void ensureValidInput(TvInputInfo inputInfo) { 20079e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee if (inputInfo.getId() == null || !mComponent.equals(inputInfo.getComponent())) { 20084f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("Invalid TvInputInfo"); 20094f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20104f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20114f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20124f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private void addTvInputLocked(TvInputInfo inputInfo) { 20139e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 20144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mInputList.add(inputInfo); 20154f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee buildTvInputListLocked(mUserId); 20164f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20174f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 20183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 20194f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo inputInfo) { 20204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20214f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 2022187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 20234f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHardwareTvInput(deviceId, inputInfo); 20244f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 20254f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 20264f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2027187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 20284f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee @Override 20294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHdmiCecTvInput(int logicalAddress, TvInputInfo inputInfo) { 20304f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureValidInput(inputInfo); 20324f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 20334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.addHdmiCecTvInput(logicalAddress, inputInfo); 20344f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee addTvInputLocked(inputInfo); 20353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2036187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2037187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2038187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2039187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void removeTvInput(String inputId) { 20404f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ensureHardwarePermission(); 20413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 20429e8ade2eb7ee835963473c9cf6faaf5423b0b048Ji-Hwan Lee ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); 2043187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim boolean removed = false; 2044187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (Iterator<TvInputInfo> it = serviceState.mInputList.iterator(); 2045187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.hasNext(); ) { 2046187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (it.next().getId().equals(inputId)) { 2047187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim it.remove(); 2048187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim removed = true; 2049187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 2050187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2051187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2052187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (removed) { 2053187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim buildTvInputListLocked(mUserId); 20544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mTvInputHardwareManager.removeTvInput(inputId); 2055187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } else { 2056187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "TvInputInfo with inputId=" + inputId + " not found."); 2057187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 20583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 20603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 206131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 206231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final class LogHandler extends Handler { 206331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_OPEN_ENTRY = 1; 206431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_UPDATE_ENTRY = 2; 206531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_CLOSE_ENTRY = 3; 206631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 206731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public LogHandler(Looper looper) { 206831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 206931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 207031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 207131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 207231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 207331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 207431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_OPEN_ENTRY: { 207531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 207631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 207731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 207831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 207931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 208031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 208131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 208231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 208331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_UPDATE_ENTRY: { 208431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 208531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 208631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 208731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 208831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onUpdateEntry(uri, channelId, time); 208931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 209031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 209131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 209231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_CLOSE_ENTRY: { 209331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 209431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 209531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg2; 209631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onCloseEntry(uri, time); 209731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 209831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 209931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 21016a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 210231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 210331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 210631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 210731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onOpenEntry(Uri uri, long channelId, long watchStarttime) { 210831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 2109f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_TITLE, 2110f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, 2111f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, 2112bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcbJae Seo TvContract.Programs.COLUMN_SHORT_DESCRIPTION 211331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2114f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " 2115f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND " 2116f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + ">?"; 211731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] selectionArgs = { 211831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(channelId), 211931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime), 212031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime) 212131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 2122f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String sortOrder = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + " ASC"; 212331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 212431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 212531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection, 212631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo selection, selectionArgs, sortOrder); 212731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 212831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2129f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, cursor.getString(0)); 2130f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 2131f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo cursor.getLong(1)); 213231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(2); 2133f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 2134f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3)); 213531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 213631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 213731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Schedule an update when the current program ends. 213831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 213931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg1 = uri; 214031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = channelId; 214131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = endTime; 214231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args); 214331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo sendMessageDelayed(msg, endTime - System.currentTimeMillis()); 214431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 214531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 214631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 214731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 214831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 214931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 215031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 215131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 215231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onUpdateEntry(Uri uri, long channelId, long time) { 215331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 2154f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 2155f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 2156f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_TITLE, 2157f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 2158f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, 2159f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_DESCRIPTION 216031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 216131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 216231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 216331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(uri, projection, null, null, null); 216431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 216531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchStartTime = cursor.getLong(0); 216631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchEndTime = cursor.getLong(1); 216731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String title = cursor.getString(2); 216831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long startTime = cursor.getLong(3); 216931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(4); 217031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String description = cursor.getString(5); 217131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 217231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Do nothing if the current log entry is already closed. 217331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (watchEndTime > 0) { 217431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 217531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 217631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 217731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // The current program has just ended. Create a (complete) log entry off the 217831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // current entry. 217931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2180f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 218131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo watchStartTime); 2182f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, time); 2183f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 2184f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, title); 2185f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, startTime); 2186f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 2187f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, description); 218831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 218931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 219031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 219131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 219231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 219331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 219431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 219531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Re-open the current log entry with the next program information. 219631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 219731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 219831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 219931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onCloseEntry(Uri uri, long watchEndTime) { 220031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 2201f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime); 220231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 220331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 220431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 2205969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2206187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim final class HardwareListener implements TvInputHardwareManager.Listener { 2207187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2208187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state) { 2209969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2210969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 2211969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2212969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2213187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2214187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 2215187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info) { 2216187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2217187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2218187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2219187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2220187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2221187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 2222187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim serviceState.mService.notifyHardwareAdded(info); 2223187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2224187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareAdded", e); 2225187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2226187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2227187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2228187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2229187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2230187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 22314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { 2232187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 2233187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim UserState userState = getUserStateLocked(mCurrentUserId); 2234187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Broadcast the event to all hardware inputs. 2235187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim for (ServiceState serviceState : userState.serviceStateMap.values()) { 2236187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim if (!serviceState.mIsHardware || serviceState.mService == null) continue; 2237187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim try { 22384f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHardwareRemoved(info); 2239187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } catch (RemoteException e) { 2240187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim Slog.e(TAG, "error in notifyHardwareRemoved", e); 2241187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2242187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2243187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2244187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2245187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2246187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 224761f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang public void onHdmiCecDeviceAdded(HdmiDeviceInfo cecDeviceInfo) { 2248187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 22494f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 22504f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 22514f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 22524f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 22534f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 22544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceAdded(cecDeviceInfo); 22554f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 22564f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceAdded", e); 22574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 22584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2259187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2260187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2261187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 2262187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 226361f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang public void onHdmiCecDeviceRemoved(HdmiDeviceInfo cecDeviceInfo) { 2264187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim synchronized (mLock) { 22654f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee UserState userState = getUserStateLocked(mCurrentUserId); 22664f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee // Broadcast the event to all hardware inputs. 22674f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee for (ServiceState serviceState : userState.serviceStateMap.values()) { 22684f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (!serviceState.mIsHardware || serviceState.mService == null) continue; 22694f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee try { 22704f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee serviceState.mService.notifyHdmiCecDeviceRemoved(cecDeviceInfo); 22714f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } catch (RemoteException e) { 22724f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in notifyHdmiCecDeviceRemoved", e); 22734f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 22744f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2275187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2276187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 2277969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 22783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 2279