TvInputManagerService.java revision e821d711db1799dc51661a3ed6188f3cd942bae7
13957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/* 23957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Copyright (C) 2014 The Android Open Source Project 33957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 43957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Licensed under the Apache License, Version 2.0 (the "License"); 53957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * you may not use this file except in compliance with the License. 63957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * You may obtain a copy of the License at 73957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 83957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * http://www.apache.org/licenses/LICENSE-2.0 93957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * 103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * Unless required by applicable law or agreed to in writing, software 113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * distributed under the License is distributed on an "AS IS" BASIS, 123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * See the License for the specific language governing permissions and 143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo * limitations under the License. 153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo */ 163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopackage com.android.server.tv; 183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 19969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; 20969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED; 21969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.app.ActivityManager; 233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.BroadcastReceiver; 243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ComponentName; 255c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderOperation; 265c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.ContentProviderResult; 2731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentResolver; 2831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentUris; 2931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.content.ContentValues; 303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Context; 313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.Intent; 323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.IntentFilter; 335c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport android.content.OperationApplicationException; 343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.ServiceConnection; 353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.PackageManager; 363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ResolveInfo; 373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.content.pm.ServiceInfo; 3831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.database.Cursor; 399a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.graphics.Rect; 40d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputClient; 41d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardware; 42d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardwareCallback; 43d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputManager; 44969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.media.tv.ITvInputManagerCallback; 45d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputService; 46d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputServiceCallback; 47d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSession; 48d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputSessionCallback; 49d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvContract; 50d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputHardwareInfo; 51d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputInfo; 52d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputService; 531f213914c45c23c653f721690da2ce0718e63139Dongwon Kangimport android.media.tv.TvTrackInfo; 543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.net.Uri; 553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Binder; 56832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Choimport android.os.Bundle; 5731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Handler; 583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.IBinder; 5931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Looper; 6031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport android.os.Message; 613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.Process; 623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.RemoteException; 633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.os.UserHandle; 649a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Choimport android.util.Slog; 653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.util.SparseArray; 666a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seoimport android.view.InputChannel; 673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport android.view.Surface; 683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.internal.content.PackageMonitor; 7031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.internal.os.SomeArgs; 71e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport com.android.internal.util.IndentingPrintWriter; 7231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seoimport com.android.server.IoThread; 733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport com.android.server.SystemService; 743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 75e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport org.xmlpull.v1.XmlPullParserException; 76e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee 77e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.FileDescriptor; 78e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Leeimport java.io.IOException; 79e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kimimport java.io.PrintWriter; 803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.ArrayList; 813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.HashMap; 825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.HashSet; 833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.List; 843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seoimport java.util.Map; 855c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seoimport java.util.Set; 863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo/** This class provides a system service that manages television inputs. */ 883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seopublic final class TvInputManagerService extends SystemService { 893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // STOPSHIP: Turn debugging off. 903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final boolean DEBUG = true; 913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final String TAG = "TvInputManagerService"; 923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Context mContext; 94c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareManager mTvInputHardwareManager; 953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 9631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final ContentResolver mContentResolver; 9731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A global lock. 993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Object mLock = new Object(); 1003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // ID of the current user. 1023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int mCurrentUserId = UserHandle.USER_OWNER; 1033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A map from user id to UserState. 1053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); 1063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 10731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final Handler mLogHandler; 10831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public TvInputManagerService(Context context) { 1103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo super(context); 11131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext = context; 11331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver = context.getContentResolver(); 11431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler = new LogHandler(IoThread.get().getLooper()); 11531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 116969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager = new TvInputHardwareManager(context, new Client()); 11731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 1183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(mCurrentUserId, new UserState()); 1203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onStart() { 1253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo publishBinderService(Context.TV_INPUT_SERVICE, new BinderService()); 1263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1280ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee @Override 1290ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee public void onBootPhase(int phase) { 1300ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1310ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee registerBroadcastReceivers(); 1320ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee synchronized (mLock) { 1330ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee buildTvInputListLocked(mCurrentUserId); 1340ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1350ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 136969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.onBootPhase(phase); 1370ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee } 1380ceb7e4755015eafda29c251eac285620788a51bJi-Hwan Lee 1393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void registerBroadcastReceivers() { 1403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageMonitor monitor = new PackageMonitor() { 1413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSomePackagesChanged() { 1433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(mCurrentUserId); 1453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1475c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1485c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo @Override 1495c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo public void onPackageRemoved(String packageName, int uid) { 1505c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo synchronized (mLock) { 1515c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo UserState userState = getUserStateLocked(mCurrentUserId); 152969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (!userState.packageSet.contains(packageName)) { 1535c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo // Not a TV input package. 1545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo return; 1555c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1565c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1575c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1585c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ArrayList<ContentProviderOperation> operations = 1595c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo new ArrayList<ContentProviderOperation>(); 1605c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1615c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; 1625c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo String[] selectionArgs = { packageName }; 1635c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1645c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI) 1655c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1665c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI) 1675c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1685c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo operations.add(ContentProviderOperation 1695c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .newDelete(TvContract.WatchedPrograms.CONTENT_URI) 1705c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .withSelection(selection, selectionArgs).build()); 1715c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1725c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo ContentProviderResult[] results = null; 1735c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo try { 1745c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations); 1755c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } catch (RemoteException | OperationApplicationException e) { 1765c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.e(TAG, "error in applyBatch" + e); 1775c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1785c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 1795c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo if (DEBUG) { 1805c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid 1815c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo + ")"); 1825c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo Slog.d(TAG, "results=" + results); 1835c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1845c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo } 1853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 1863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo monitor.register(mContext, null, UserHandle.ALL, true); 1873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo IntentFilter intentFilter = new IntentFilter(); 1893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 1903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo intentFilter.addAction(Intent.ACTION_USER_REMOVED); 1913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mContext.registerReceiverAsUser(new BroadcastReceiver() { 1923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onReceive(Context context, Intent intent) { 1943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String action = intent.getAction(); 1953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (Intent.ACTION_USER_SWITCHED.equals(action)) { 1963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 1973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 1983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 1993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }, UserHandle.ALL, intentFilter, null, null); 2023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void buildTvInputListLocked(int userId) { 2053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 206969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 207969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Map<String, TvInputState> oldInputMap = userState.inputMap; 208969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.inputMap = new HashMap<String, TvInputState>(); 209969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 210969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.packageSet.clear(); 2113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho if (DEBUG) Slog.d(TAG, "buildTvInputList"); 2133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo PackageManager pm = mContext.getPackageManager(); 2143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo List<ResolveInfo> services = pm.queryIntentServices( 215e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee new Intent(TvInputService.SERVICE_INTERFACE), 216e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 2173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ResolveInfo ri : services) { 2183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ServiceInfo si = ri.serviceInfo; 2193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { 2209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission " 2213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + android.Manifest.permission.BIND_TV_INPUT); 2223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo continue; 2233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 224e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee try { 225e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee TvInputInfo info = TvInputInfo.createTvInputInfo(mContext, ri); 226e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee if (DEBUG) Slog.d(TAG, "add " + info.getId()); 227969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState state = oldInputMap.get(info.getId()); 228969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (state == null) { 229969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state = new TvInputState(); 230969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 231969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.inputMap.put(info.getId(), state); 232969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mInfo = info; 233969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.packageSet.add(si.packageName); 234226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim 235226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Reconnect the service if existing input is updated. 236226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim updateServiceConnectionLocked(info.getId(), userId); 237e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } catch (IOException | XmlPullParserException e) { 238e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee Slog.e(TAG, "Can't load TV input " + si.name, e); 239e7bb7d6bb2257c24076f5a4b9f536f90a6637f58Chulwoo Lee } 2403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 241969167dc05a6485a32d160895871cff46fd81884Wonsik Kim oldInputMap.clear(); 2423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void switchUser(int userId) { 2453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 2463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (mCurrentUserId == userId) { 2473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 2483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // final int oldUserId = mCurrentUserId; 2503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // TODO: Release services and sessions in the old user state, if needed. 2513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mCurrentUserId = userId; 2523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 2543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 2553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState = new UserState(); 2563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.put(userId, userState); 2583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo buildTvInputListLocked(userId); 2593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void removeUser(int userId) { 2633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 264b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo UserState userState = mUserStates.get(userId); 265b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo if (userState == null) { 266b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo return; 267b06cb8870f0407f18bb1225065a93aba2a5de2bfJae Seo } 2683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Release created sessions. 2693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (SessionState state : userState.sessionStateMap.values()) { 270d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (state.mSession != null) { 2713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 272d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim state.mSession.release(); 2733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 2749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in release", e); 2753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.sessionStateMap.clear(); 2793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 2803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Unregister all callbacks and unbind all services. 2813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo for (ServiceState serviceState : userState.serviceStateMap.values()) { 282d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mCallback != null) { 2833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 284d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 2853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 2869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in unregisterCallback", e); 2873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 28972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.clear(); 290d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 2913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userState.serviceStateMap.clear(); 2933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 29472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.clear(); 29572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 2963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserStates.remove(userId); 2973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 2993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private UserState getUserStateLocked(int userId) { 3013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = mUserStates.get(userId); 3023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (userState == null) { 3033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("User state not found for user ID " + userId); 3043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return userState; 3063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 308d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceState getServiceStateLocked(String inputId, int userId) { 3093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 310d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ServiceState serviceState = userState.serviceStateMap.get(inputId); 3113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 312d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim throw new IllegalStateException("Service state not found for " + inputId + " (userId=" 3137de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim + userId + ")"); 3143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return serviceState; 3163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) { 3193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 3203957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 3213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (sessionState == null) { 3223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalArgumentException("Session state not found for token " + sessionToken); 3233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Only the application that requested this session or the system can access it. 325d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.mCallingUid) { 3263957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new SecurityException("Illegal access to the session with token " + sessionToken 3273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + " from uid " + callingUid); 3283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return sessionState; 3302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 3322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private ITvInputSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) { 3332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 334d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ITvInputSession session = sessionState.mSession; 3353957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (session == null) { 3363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo throw new IllegalStateException("Session not yet created for token " + sessionToken); 3373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return session; 3393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 3413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private int resolveCallingUserId(int callingPid, int callingUid, int requestedUserId, 3423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo String methodName) { 3433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return ActivityManager.handleIncomingUser(callingPid, callingUid, requestedUserId, false, 3443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo false, methodName, null); 3453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 347d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void updateServiceConnectionLocked(String inputId, int userId) { 3483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(userId); 349d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ServiceState serviceState = userState.serviceStateMap.get(inputId); 3503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 3513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting) { 3542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!serviceState.mSessionTokens.isEmpty()) { 3552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // wait until all the sessions are removed. 3562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 3572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 3582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = false; 3592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 36072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim boolean isStateEmpty = serviceState.mClientTokens.isEmpty() 361d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim && serviceState.mSessionTokens.isEmpty(); 362d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService == null && !isStateEmpty && userId == mCurrentUserId) { 3633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is not yet connected but its state indicates that we 3643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // have pending requests. Then, connect the service. 365d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mBound) { 3663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // We have already bound to the service so we don't try to bind again until after we 3673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // unbind later on. 3683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 3693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 371d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim Slog.d(TAG, "bindServiceAsUser(inputId=" + inputId + ", userId=" + userId 3723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo + ")"); 3733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 374d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim 375d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent( 376969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.inputMap.get(inputId).mInfo.getComponent()); 377226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // Binding service may fail if the service is updating. 378226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // In that case, the connection will be revived in buildTvInputListLocked called by 379226a51958d645a8e2be3e40a6b6daaca558b4913Jaewan Kim // onSomePackagesChanged. 380e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee serviceState.mBound = mContext.bindServiceAsUser( 381e17b2dd7bcc137bf4d842a779e8d62c63957a978Ji-Hwan Lee i, serviceState.mConnection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); 382d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim } else if (serviceState.mService != null && isStateEmpty) { 3833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // This means that the service is already connected but its state indicates that we have 3843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // nothing to do with it. Then, disconnect the service. 3853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 386d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim Slog.d(TAG, "unbindService(inputId=" + inputId + ")"); 3873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 388d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mContext.unbindService(serviceState.mConnection); 389d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim userState.serviceStateMap.remove(inputId); 3903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 3923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 39372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private ClientState createClientStateLocked(IBinder clientToken, int userId) { 39472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 39572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = new ClientState(clientToken, userId); 39672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 39772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientToken.linkToDeath(clientState, 0); 39872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 39972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "Client is already died."); 40072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 40172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.put(clientToken, clientState); 40272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return clientState; 40372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 40472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 4053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken, 4067de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim final int userId) { 40772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final UserState userState = getUserStateLocked(userId); 40872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim final SessionState sessionState = userState.sessionStateMap.get(sessionToken); 4093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 410d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInputId + ")"); 4113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4126a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4136a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString()); 4146a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo 4153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Set up a callback to send the session token. 4163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() { 4173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 4183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onSessionCreated(ITvInputSession session) { 4193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 420d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim Slog.d(TAG, "onSessionCreated(inputId=" + sessionState.mInputId + ")"); 4213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 423d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mSession = session; 424fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (session == null) { 425fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 4262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId, 4275c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo null, null, sessionState.mSeq); 428fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } else { 4292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 4302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim session.asBinder().linkToDeath(sessionState, 0); 4312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 4322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "Session is already died."); 4332b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 43472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 43572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim IBinder clientToken = sessionState.mClient.asBinder(); 43672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 43772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState == null) { 43872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState = createClientStateLocked(clientToken, userId); 43972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 44072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.add(sessionState.mSessionToken); 44172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 442d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId, 4435c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sessionToken, channels[0], sessionState.mSeq); 444fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 4456a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[0].dispose(); 4463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 4473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 448832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho 449832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho @Override 4501f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onChannelRetuned(Uri channelUri) { 451a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 452a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 4531f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); 454a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 455a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 456a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 457a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 458a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 4591f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // TODO: Consider adding this channel change in the watch log. When we do 4601f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // that, how we can protect the watch log from malicious tv inputs should 4611f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // be addressed. e.g. add a field which represents where the channel change 4621f213914c45c23c653f721690da2ce0718e63139Dongwon Kang // originated from. 4631f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); 464a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 4651f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onChannelRetuned"); 466a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 467a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 468a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 469a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang 470a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang @Override 4711f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void onTrackInfoChanged(List<TvTrackInfo> tracks) { 472a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang synchronized (mLock) { 473a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (DEBUG) { 4741f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.d(TAG, "onTrackInfoChanged(" + tracks + ")"); 475a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 476a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 477a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang return; 478a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } 479a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang try { 4801f213914c45c23c653f721690da2ce0718e63139Dongwon Kang sessionState.mClient.onTrackInfoChanged(tracks, 481a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang sessionState.mSeq); 482a3be12a236aef0d9c4ff1274075f1e7899d29153Dongwon Kang } catch (RemoteException e) { 4831f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in onTrackInfoChanged"); 484b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 485b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 486b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang } 487b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang 488b93ccca6139a7ee2dba5c110e5f8213a2bd231e5Dongwon Kang @Override 4899b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoAvailable() { 4909b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 4919b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 4929b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoAvailable()"); 4939b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 4949b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 4959b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 4969b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 4979b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 4989b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoAvailable(sessionState.mSeq); 4999b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5009b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoAvailable"); 5019b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5029b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5039b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5049b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5059b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 5069b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang public void onVideoUnavailable(int reason) { 5079b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang synchronized (mLock) { 5089b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (DEBUG) { 5099b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.d(TAG, "onVideoUnavailable(" + reason + ")"); 5109b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5119b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang if (sessionState.mSession == null || sessionState.mClient == null) { 5129b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang return; 5139b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5149b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang try { 5159b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq); 5169b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } catch (RemoteException e) { 5179b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang Slog.e(TAG, "error in onVideoUnavailable"); 5189b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5199b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5209b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang } 5219b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang 5229b08edff236fc68d836eccfaa1a5f028dc390cecDongwon Kang @Override 523832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho public void onSessionEvent(String eventType, Bundle eventArgs) { 524832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho synchronized (mLock) { 525832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (DEBUG) { 526832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.d(TAG, "onEvent(what=" + eventType + ", data=" + eventArgs + ")"); 527832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 528832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho if (sessionState.mSession == null || sessionState.mClient == null) { 529832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho return; 530832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 531832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho try { 532832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mClient.onSessionEvent(eventType, eventArgs, 533832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho sessionState.mSeq); 534832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } catch (RemoteException e) { 535832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho Slog.e(TAG, "error in onSessionEvent"); 536832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 537832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 538832860fb9f6b3a7188a6af2d5d67806593595800Youngsang Cho } 5393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo }; 5403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 5413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Create a session. When failed, send a null token immediately. 5423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 5436a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo service.createSession(channels[1], callback); 5443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 5459a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createSession", e); 546fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang removeSessionStateLocked(sessionToken, userId); 547d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId, null, null, 5485c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sessionState.mSeq); 5493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5506a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo channels[1].dispose(); 5513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 553d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId, 5545c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo IBinder sessionToken, InputChannel channel, int seq) { 5553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 556d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim client.onSessionCreated(inputId, sessionToken, channel, seq); 5573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException exception) { 5589a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in onSessionCreated", exception); 5593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 5613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 5622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) { 5632b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId); 5642b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession != null) { 5652b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 5662b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession.release(); 5672b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 5682b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.w(TAG, "session is already disapeared", e); 5692b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 5702b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sessionState.mSession = null; 5713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5722b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, userId); 5733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 5743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 575fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang private void removeSessionStateLocked(IBinder sessionToken, int userId) { 576fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang // Remove the session state from the global session state map of the current user. 577fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang UserState userState = getUserStateLocked(userId); 578fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang SessionState sessionState = userState.sessionStateMap.remove(sessionToken); 579fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 58031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry, if any. 581d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 58231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 583d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 58431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = System.currentTimeMillis(); 58531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget(); 58631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 58731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 58872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Also remove the session token from the session token list of the current client and 58972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // service. 59072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder()); 59172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 59272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.remove(sessionToken); 59372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 59472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(sessionState.mClient.asBinder()); 59572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 59672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 59772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 598d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ServiceState serviceState = userState.serviceStateMap.get(sessionState.mInputId); 599fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang if (serviceState != null) { 600d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.remove(sessionToken); 601fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 602d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim updateServiceConnectionLocked(sessionState.mInputId, userId); 603fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang } 604fd5b72f1ed2ee74a4204eef65f560fc82f0b62feDongwon Kang 605969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void unregisterClientInternalLocked(IBinder clientToken, String inputId, 60672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim int userId) { 60772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(userId); 60872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(clientToken); 60972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 61072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mInputIds.remove(inputId); 61172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState.isEmpty()) { 61272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim userState.clientStateMap.remove(clientToken); 61372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 61472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 61572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 61672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ServiceState serviceState = userState.serviceStateMap.get(inputId); 61772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (serviceState == null) { 61872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 61972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 62072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 62172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // Remove this client from the client list and unregister the callback. 62272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mClientTokens.remove(clientToken); 62372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (!serviceState.mClientTokens.isEmpty()) { 62472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // We have other clients who want to keep the callback. Do this later. 62572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 62672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 62772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (serviceState.mService == null || serviceState.mCallback == null) { 62872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return; 62972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 63072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim try { 63172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mService.unregisterCallback(serviceState.mCallback); 63272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } catch (RemoteException e) { 63372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim Slog.e(TAG, "error in unregisterCallback", e); 63472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } finally { 63572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim serviceState.mCallback = null; 63672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim updateServiceConnectionLocked(inputId, userId); 63772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 63872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 63972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 640969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void notifyStateChangedLocked(UserState userState, String inputId, 641969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state, ITvInputManagerCallback targetCallback) { 642969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (DEBUG) { 643969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.d(TAG, "notifyStateChangedLocked: inputId = " + inputId 644969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + "; state = " + state); 645969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 646969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (targetCallback == null) { 647969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 648969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 649969167dc05a6485a32d160895871cff46fd81884Wonsik Kim callback.onInputStateChanged(inputId, state); 650969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } catch (RemoteException e) { 651969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 652969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 653969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 654969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 6552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 656969167dc05a6485a32d160895871cff46fd81884Wonsik Kim targetCallback.onInputStateChanged(inputId, state); 6572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch (RemoteException e) { 658969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.e(TAG, "Failed to report state change to callback."); 6592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 6622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 663969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private void setStateLocked(String inputId, int state, int userId) { 664969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(userId); 665969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 666969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(inputId); 667969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int oldState = inputState.mState; 668969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState = state; 669969167dc05a6485a32d160895871cff46fd81884Wonsik Kim boolean isStateEmpty = serviceState.mClientTokens.isEmpty() 670969167dc05a6485a32d160895871cff46fd81884Wonsik Kim && serviceState.mSessionTokens.isEmpty(); 671969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (serviceState != null && serviceState.mService == null && !isStateEmpty) { 672969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // We don't notify state change while reconnecting. It should remain disconnected. 673969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 674969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 675969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (oldState != state) { 676969167dc05a6485a32d160895871cff46fd81884Wonsik Kim notifyStateChangedLocked(userState, inputId, state, null); 677969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 678969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 679969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 6803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class BinderService extends ITvInputManager.Stub { 6813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 6823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public List<TvInputInfo> getTvInputList(int userId) { 6833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 6843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "getTvInputList"); 6853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 6863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 6873957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 6883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 689969167dc05a6485a32d160895871cff46fd81884Wonsik Kim List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); 690969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 691969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputList.add(state.mInfo); 6923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 693969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return inputList; 6943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 6963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 6973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 6993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 7003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 701969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerCallback(final ITvInputManagerCallback callback, int userId) { 7023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 7033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "registerCallback"); 7043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 7053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 7063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 7073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 708969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.add(callback); 709969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 710969167dc05a6485a32d160895871cff46fd81884Wonsik Kim notifyStateChangedLocked(userState, state.mInfo.getId(), 711969167dc05a6485a32d160895871cff46fd81884Wonsik Kim state.mState, callback); 7123957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 7153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 7163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 7193957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 720969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void unregisterCallback(ITvInputManagerCallback callback, int userId) { 7213957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), 7223957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.getCallingUid(), userId, "unregisterCallback"); 7233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 7243957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 7253957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 726969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(resolvedUserId); 727969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.callbackSet.remove(callback); 7283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 7303957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 7313957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7323957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7333957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 7343957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 735d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim public void createSession(final ITvInputClient client, final String inputId, 7363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo int seq, int userId) { 7373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 7383957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 7393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "createSession"); 7403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 7413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 7423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 7433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo UserState userState = getUserStateLocked(resolvedUserId); 744d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim ServiceState serviceState = userState.serviceStateMap.get(inputId); 7453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (serviceState == null) { 746d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState = new ServiceState( 747969167dc05a6485a32d160895871cff46fd81884Wonsik Kim userState.inputMap.get(inputId).mInfo, resolvedUserId); 748d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim userState.serviceStateMap.put(inputId, serviceState); 7493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7502b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send a null token immediately while reconnecting. 7512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState.mReconnecting == true) { 7525c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sendSessionTokenToClientLocked(client, inputId, null, null, seq); 7532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim return; 7542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 7552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 7562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Create a new session token and a session state. 7572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim IBinder sessionToken = new Binder(); 75872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim SessionState sessionState = new SessionState(sessionToken, inputId, client, 75972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim seq, callingUid, resolvedUserId); 7602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 7612b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Add them to the global session state map of the current user. 7622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim userState.sessionStateMap.put(sessionToken, sessionState); 7632b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 7642b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Also, add them to the session state map of the current service. 765d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mSessionTokens.add(sessionToken); 7663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 767d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (serviceState.mService != null) { 768d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, 7697de5e234715a3baa8905afa3dd0c5009af64541fSungsoo Lim resolvedUserId); 7703957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } else { 771d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim updateServiceConnectionLocked(inputId, resolvedUserId); 7723957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 7753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 7763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7773957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 7793957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 7803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void releaseSession(IBinder sessionToken, int userId) { 7813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 7823957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 7833957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "releaseSession"); 7843957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 7853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 7863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 7872b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim releaseSessionLocked(sessionToken, callingUid, resolvedUserId); 7883957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 7903957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 7913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7923957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 7933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 7943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 7953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setSurface(IBinder sessionToken, Surface surface, int userId) { 7963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 7973957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 7983957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setSurface"); 7993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8003957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8023957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).setSurface( 8043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo surface); 8053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 8069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setSurface", e); 8073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 810f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho if (surface != null) { 811f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho // surface is not used in TvInputManagerService. 812f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho surface.release(); 813f836206818ce338db83a3c23c486fb8cab29cb6dYoungsang Cho } 8143957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8153957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8163957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 819e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, 820e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho int height, int userId) { 821e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int callingUid = Binder.getCallingUid(); 822e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 823e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho userId, "dispatchSurfaceChanged"); 824e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho final long identity = Binder.clearCallingIdentity(); 825e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 826e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho synchronized (mLock) { 827e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho try { 828e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 829e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho .dispatchSurfaceChanged(format, width, height); 830e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } catch (RemoteException e) { 831e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Slog.e(TAG, "error in dispatchSurfaceChanged", e); 832e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 833e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 834e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } finally { 835e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho Binder.restoreCallingIdentity(identity); 836e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 837e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho } 838e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho 839e821d711db1799dc51661a3ed6188f3cd942bae7Youngsang Cho @Override 8403957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void setVolume(IBinder sessionToken, float volume, int userId) { 8413957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 8423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 8433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "setVolume"); 8443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8463957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).setVolume( 8493957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo volume); 8503957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 8519a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in setVolume", e); 8523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 8553957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 8563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8573957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 8583957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 8593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 8603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void tune(IBinder sessionToken, final Uri channelUri, int userId) { 8613957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int callingUid = Binder.getCallingUid(); 8623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 8633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo userId, "tune"); 8643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo final long identity = Binder.clearCallingIdentity(); 8653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 8673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 8683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(channelUri); 86931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 87031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long currentTime = System.currentTimeMillis(); 87131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = ContentUris.parseId(channelUri); 87231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 87331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Close the open log entry first, if any. 87431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo UserState userState = getUserStateLocked(resolvedUserId); 87531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SessionState sessionState = userState.sessionStateMap.get(sessionToken); 876d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim if (sessionState.mLogUri != null) { 87731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 878d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 87931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = currentTime; 88031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args) 88131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo .sendToTarget(); 88231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 88331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 88431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Create a log entry and fill it later. 885969167dc05a6485a32d160895871cff46fd81884Wonsik Kim String packageName = userState.inputMap.get(sessionState.mInputId).mInfo 8865c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo .getServiceInfo().packageName; 88731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 8885c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName); 889f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 89031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo currentTime); 891f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0); 892f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 89331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 894d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim sessionState.mLogUri = mContentResolver.insert( 89531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo TvContract.WatchedPrograms.CONTENT_URI, values); 89631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 897d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim args.arg1 = sessionState.mLogUri; 89831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = ContentUris.parseId(channelUri); 89931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = currentTime; 90031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget(); 9013957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 9029a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in tune", e); 9033957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo return; 9043957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9053957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } finally { 9073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo Binder.restoreCallingIdentity(identity); 9083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 9109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 9119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 9122c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo public void setCaptionEnabled(IBinder sessionToken, boolean enabled, int userId) { 9132c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int callingUid = Binder.getCallingUid(); 9142c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9152c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo userId, "setCaptionEnabled"); 9162c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo final long identity = Binder.clearCallingIdentity(); 9172c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 9182c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo synchronized (mLock) { 9192c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo try { 9202c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo getSessionLocked(sessionToken, callingUid, resolvedUserId) 9212c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo .setCaptionEnabled(enabled); 9222c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } catch (RemoteException e) { 9232c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Slog.e(TAG, "error in setCaptionEnabled", e); 9242c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 9252c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 9262c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } finally { 9272c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo Binder.restoreCallingIdentity(identity); 9282c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 9292c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo } 9302c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo 9312c1c31c7ae9bd972b974a5cc2d8b0942746af612Jae Seo @Override 9321f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void selectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 9331f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 9341f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9351f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "selectTrack"); 9361f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 9371f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 9381f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 9391f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 9401f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack( 9411f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 9421f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 9431f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in selectTrack", e); 9441f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9451f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9461f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 9471f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 9481f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9491f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9501f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 9511f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 9521f213914c45c23c653f721690da2ce0718e63139Dongwon Kang public void unselectTrack(IBinder sessionToken, TvTrackInfo track, int userId) { 9531f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int callingUid = Binder.getCallingUid(); 9541f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9551f213914c45c23c653f721690da2ce0718e63139Dongwon Kang userId, "unselectTrack"); 9561f213914c45c23c653f721690da2ce0718e63139Dongwon Kang final long identity = Binder.clearCallingIdentity(); 9571f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 9581f213914c45c23c653f721690da2ce0718e63139Dongwon Kang synchronized (mLock) { 9591f213914c45c23c653f721690da2ce0718e63139Dongwon Kang try { 9601f213914c45c23c653f721690da2ce0718e63139Dongwon Kang getSessionLocked(sessionToken, callingUid, resolvedUserId).unselectTrack( 9611f213914c45c23c653f721690da2ce0718e63139Dongwon Kang track); 9621f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } catch (RemoteException e) { 9631f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Slog.e(TAG, "error in unselectTrack", e); 9641f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9651f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9661f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } finally { 9671f213914c45c23c653f721690da2ce0718e63139Dongwon Kang Binder.restoreCallingIdentity(identity); 9681f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9691f213914c45c23c653f721690da2ce0718e63139Dongwon Kang } 9701f213914c45c23c653f721690da2ce0718e63139Dongwon Kang 9711f213914c45c23c653f721690da2ce0718e63139Dongwon Kang @Override 9729a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, 9739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho int userId) { 9749a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 9759a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9769a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "createOverlayView"); 9779a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 9789a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 9799a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 9809a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 9819a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 9829a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .createOverlayView(windowToken, frame); 9839a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 9849a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in createOverlayView", e); 9859a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 9869a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 9879a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 9889a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 9899a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 9909a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 9919a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 9929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 9939a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) { 9949a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 9959a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 9969a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "relayoutOverlayView"); 9979a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 9989a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 9999a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 10009a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 10019a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 10029a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .relayoutOverlayView(frame); 10039a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 10049a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in relayoutOverlayView", e); 10059a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10069a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10079a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 10089a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 10099a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10109a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10119a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho 10129a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho @Override 10139a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho public void removeOverlayView(IBinder sessionToken, int userId) { 10149a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int callingUid = Binder.getCallingUid(); 10159a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 10169a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho userId, "removeOverlayView"); 10179a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho final long identity = Binder.clearCallingIdentity(); 10189a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 10199a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho synchronized (mLock) { 10209a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho try { 10219a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho getSessionLocked(sessionToken, callingUid, resolvedUserId) 10229a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho .removeOverlayView(); 10239a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } catch (RemoteException e) { 10249a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in removeOverlayView", e); 10259a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10269a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10279a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } finally { 10289a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Binder.restoreCallingIdentity(identity); 10299a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 10309a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho } 1031c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1032c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1033c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { 1034969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1035c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1036c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1037c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1038c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1039c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1040c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1041c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.getHardwareList(); 1042c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1043c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1044c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1045c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1046c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1047c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1048969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void registerTvInputInfo(TvInputInfo info, int deviceId) { 1049969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1050969167dc05a6485a32d160895871cff46fd81884Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1051969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return; 1052969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1053969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1054969167dc05a6485a32d160895871cff46fd81884Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1055969167dc05a6485a32d160895871cff46fd81884Wonsik Kim try { 1056969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mTvInputHardwareManager.registerTvInputInfo(info, deviceId); 1057969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } finally { 1058969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Binder.restoreCallingIdentity(identity); 1059969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1060969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1061969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1062969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1063c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireTvInputHardware(int deviceId, 1064969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ITvInputHardwareCallback callback, TvInputInfo info, int userId) 1065969167dc05a6485a32d160895871cff46fd81884Wonsik Kim throws RemoteException { 1066969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1067c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1068c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 1069c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1070c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1071c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1072c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1073c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1074c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "acquireTvInputHardware"); 1075c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1076c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mTvInputHardwareManager.acquireHardware( 1077969167dc05a6485a32d160895871cff46fd81884Wonsik Kim deviceId, callback, info, callingUid, resolvedUserId); 1078c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1079c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1080c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1081c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1082c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1083c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1084c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId) 1085c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 1086969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) 1087c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim != PackageManager.PERMISSION_GRANTED) { 1088c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 1089c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1090c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 1091c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final long identity = Binder.clearCallingIdentity(); 1092c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int callingUid = Binder.getCallingUid(); 1093c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, 1094c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim userId, "releaseTvInputHardware"); 1095c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 1096c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mTvInputHardwareManager.releaseHardware( 1097c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId, hardware, callingUid, resolvedUserId); 1098c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } finally { 1099c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Binder.restoreCallingIdentity(identity); 1100c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1101c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 1102e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1103e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim @Override 11040f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo @SuppressWarnings("resource") 1105e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) { 1106e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 11070f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1108e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim != PackageManager.PERMISSION_GRANTED) { 11090f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo pw.println("Permission Denial: can't dump TvInputManager from pid=" 11100f8fc345ea61928265fdd6d461bf1babe353fbe4Jae Seo + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1111e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim return; 1112e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1113e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1114e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim synchronized (mLock) { 1115e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("User Ids (Current user: " + mCurrentUserId + "):"); 1116e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1117e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1118e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1119e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(Integer.valueOf(userId)); 1120e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1121e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1122e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1123e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (int i = 0; i < mUserStates.size(); i++) { 1124e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim int userId = mUserStates.keyAt(i); 1125e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim UserState userState = getUserStateLocked(userId); 1126e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("UserState (" + userId + "):"); 1127e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1128e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1129969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("inputMap: inputId -> TvInputState"); 1130e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1131969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (TvInputState state : userState.inputMap.values()) { 1132969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(state.toString()); 1133e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1134e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1135e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1136969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("packageSet:"); 1137e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1138969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (String packageName : userState.packageSet) { 1139e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(packageName); 1140e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1141e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1142e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1143e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("clientStateMap: ITvInputClient -> ClientState"); 1144e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1145e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, ClientState> entry : 1146e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.clientStateMap.entrySet()) { 1147e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ClientState client = entry.getValue(); 1148e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + client); 1149e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1150e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1151e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1152e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mInputIds:"); 1153e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1154e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (String inputId : client.mInputIds) { 1155e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(inputId); 1156e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1157e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1158e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1159e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1160e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1161e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : client.mSessionTokens) { 1162e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1163e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1164e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1165e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1166e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens: " + client.mClientToken); 1167e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + client.mUserId); 1168e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1169e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1170e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1171e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1172e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1173e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("serviceStateMap: inputId -> ServiceState"); 1174e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1175e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<String, ServiceState> entry : 1176e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.serviceStateMap.entrySet()) { 1177e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim ServiceState service = entry.getValue(); 1178e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + service); 1179e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1180e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1181e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1182e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClientTokens:"); 1183e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1184e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mClientTokens) { 1185e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1186e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1187e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1188e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1189e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionTokens:"); 1190e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1191e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (IBinder token : service.mSessionTokens) { 1192e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("" + token); 1193e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1194e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1195e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1196e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mService: " + service.mService); 1197e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallback: " + service.mCallback); 1198e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mBound: " + service.mBound); 1199e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mReconnecting: " + service.mReconnecting); 1200e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1201e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1202e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1203e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1204e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1205e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("sessionStateMap: ITvInputSession -> SessionState"); 1206e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1207e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim for (Map.Entry<IBinder, SessionState> entry : 1208e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim userState.sessionStateMap.entrySet()) { 1209e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim SessionState session = entry.getValue(); 1210e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println(entry.getKey() + ": " + session); 1211e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1212e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.increaseIndent(); 1213e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mInputId: " + session.mInputId); 1214e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mClient: " + session.mClient); 1215e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSeq: " + session.mSeq); 1216e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mCallingUid: " + session.mCallingUid); 1217e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mUserId: " + session.mUserId); 1218e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSessionToken: " + session.mSessionToken); 1219e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mSession: " + session.mSession); 1220e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.println("mLogUri: " + session.mLogUri); 1221e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1222e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1223e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1224e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim 1225969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println("callbackSet:"); 1226969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.increaseIndent(); 1227969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (ITvInputManagerCallback callback : userState.callbackSet) { 1228969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.println(callback.toString()); 1229969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1230969167dc05a6485a32d160895871cff46fd81884Wonsik Kim pw.decreaseIndent(); 1231969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1232e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim pw.decreaseIndent(); 1233e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1234e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 1235e14c3f4fc42e2dc83cf4aba711c5ff52d8bbe3eaJaewan Kim } 12363957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12373957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1238969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private static final class TvInputState { 1239969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A TvInputInfo object which represents the TV input. 1240969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 1241969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1242969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // The state of TV input. Connected by default. 1243969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int mState = INPUT_STATE_CONNECTED; 1244969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1245969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 1246969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public String toString() { 1247969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return "mInfo: " + mInfo + "; mState: " + mState; 1248969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1249969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1250969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 12513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private static final class UserState { 1252969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A mapping from the TV input id to its TvInputState. 1253969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); 12543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1255969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of all TV input packages. 1256969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<String> packageSet = new HashSet<String>(); 12575c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo 125872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // A mapping from the token of a client to its state. 125972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final Map<IBinder, ClientState> clientStateMap = 126072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim new HashMap<IBinder, ClientState>(); 126172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 12623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the name of a TV input service to its state. 1263d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final Map<String, ServiceState> serviceStateMap = 1264d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim new HashMap<String, ServiceState>(); 12653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 12663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // A mapping from the token of a TV input session to its state. 12673957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final Map<IBinder, SessionState> sessionStateMap = 12683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo new HashMap<IBinder, SessionState>(); 1269969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1270969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // A set of callbacks. 1271969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final Set<ITvInputManagerCallback> callbackSet = 1272969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new HashSet<ITvInputManagerCallback>(); 12733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 12743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 127572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final class ClientState implements IBinder.DeathRecipient { 127672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<String> mInputIds = new ArrayList<String>(); 127772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 127872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 127972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private IBinder mClientToken; 128072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final int mUserId; 128172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 128272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState(IBinder clientToken, int userId) { 128372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = clientToken; 128472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mUserId = userId; 128572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 128672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 128772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public boolean isEmpty() { 128872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim return mInputIds.isEmpty() && mSessionTokens.isEmpty(); 128972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 129072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 129172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim @Override 129272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim public void binderDied() { 129372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim synchronized (mLock) { 129472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim UserState userState = getUserStateLocked(mUserId); 129572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim // DO NOT remove the client state of clientStateMap in this method. It will be 1296969167dc05a6485a32d160895871cff46fd81884Wonsik Kim // removed in releaseSessionLocked() or unregisterClientInternalLocked(). 129772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim ClientState clientState = userState.clientStateMap.get(mClientToken); 129872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (clientState != null) { 129972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mSessionTokens.size() > 0) { 130072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim releaseSessionLocked( 130172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId); 130272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 130372ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim while (clientState.mInputIds.size() > 0) { 1304969167dc05a6485a32d160895871cff46fd81884Wonsik Kim unregisterClientInternalLocked( 130572ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken, clientState.mInputIds.get(0), mUserId); 130672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 130772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 130872ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mClientToken = null; 130972ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 131072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 131172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim } 131272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim 13133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceState { 131472ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final List<IBinder> mClientTokens = new ArrayList<IBinder>(); 1315d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final List<IBinder> mSessionTokens = new ArrayList<IBinder>(); 1316d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ServiceConnection mConnection; 13172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final TvInputInfo mTvInputInfo; 13183957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1319d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputService mService; 1320d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceCallback mCallback; 1321d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private boolean mBound; 13222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private boolean mReconnecting; 13233957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1324d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ServiceState(TvInputInfo inputInfo, int userId) { 13252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mTvInputInfo = inputInfo; 13262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mConnection = new InputServiceConnection(inputInfo, userId); 13273957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13283957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13293957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 13302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final class SessionState implements IBinder.DeathRecipient { 1331d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final String mInputId; 1332d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final ITvInputClient mClient; 1333d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mSeq; 1334d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final int mCallingUid; 13352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim private final int mUserId; 133672ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private final IBinder mSessionToken; 1337d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private ITvInputSession mSession; 1338d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private Uri mLogUri; 13393957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 134072ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim private SessionState(IBinder sessionToken, String inputId, ITvInputClient client, int seq, 13412b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim int callingUid, int userId) { 134272ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim mSessionToken = sessionToken; 13432b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mInputId = inputId; 13442b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient = client; 13452b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSeq = seq; 13462b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mCallingUid = callingUid; 13472b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mUserId = userId; 13482b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 13492b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 13502b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim @Override 13512b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim public void binderDied() { 13522b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 13532b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mSession = null; 13542b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (mClient != null) { 13552b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim try { 13562b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim mClient.onSessionReleased(mSeq); 13572b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } catch(RemoteException e) { 13582b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim Slog.e(TAG, "error in onSessionReleased", e); 13592b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 13602b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 136172ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim removeSessionStateLocked(mSessionToken, mUserId); 13622b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 13633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13653957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 13663957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class InputServiceConnection implements ServiceConnection { 1367d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private final TvInputInfo mTvInputInfo; 13683957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 13693957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1370d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim private InputServiceConnection(TvInputInfo inputInfo, int userId) { 13713957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 1372d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim mTvInputInfo = inputInfo; 13733957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13743957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 13753957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 13763957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onServiceConnected(ComponentName name, IBinder service) { 1377969167dc05a6485a32d160895871cff46fd81884Wonsik Kim String inputId = mTvInputInfo.getId(); 13783957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 1379969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.d(TAG, "onServiceConnected(inputId=" + inputId + ")"); 13803957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13813957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1382969167dc05a6485a32d160895871cff46fd81884Wonsik Kim UserState userState = getUserStateLocked(mUserId); 1383969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ServiceState serviceState = userState.serviceStateMap.get(inputId); 1384d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService = ITvInputService.Stub.asInterface(service); 13853957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 13863957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // Register a callback, if we need to. 138772ad7bf915ce40d8437a4ee2518ae07b73502e12Sungsoo Lim if (!serviceState.mClientTokens.isEmpty() && serviceState.mCallback == null) { 1388969167dc05a6485a32d160895871cff46fd81884Wonsik Kim serviceState.mCallback = new ServiceCallback(mTvInputInfo.getId(), mUserId); 13893957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo try { 1390d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim serviceState.mService.registerCallback(serviceState.mCallback); 13913957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } catch (RemoteException e) { 13929a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho Slog.e(TAG, "error in registerCallback", e); 13933957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13943957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 13953957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 13963957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo // And create sessions, if any. 1397d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 1398d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim createSessionInternalLocked(serviceState.mService, sessionToken, mUserId); 13993957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 1400969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1401969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputState inputState = userState.inputMap.get(inputId); 1402969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (inputState != null && inputState.mState != INPUT_STATE_DISCONNECTED) { 1403969167dc05a6485a32d160895871cff46fd81884Wonsik Kim notifyStateChangedLocked(userState, mTvInputInfo.getId(), 1404969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputState.mState, null); 1405969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 14063957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14073957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14083957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 14093957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 14103957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo public void onServiceDisconnected(ComponentName name) { 14113957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 1412d6672b51c5e07ec376a61057cfbb6bb7491a76b3Sungsoo Lim Slog.d(TAG, "onServiceDisconnected(inputId=" + mTvInputInfo.getId() + ")"); 14133957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14142b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (!mTvInputInfo.getComponent().equals(name)) { 14152b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim throw new IllegalArgumentException("Mismatched ComponentName: " 14162b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim + mTvInputInfo.getComponent() + " (expected), " + name + " (actual)."); 14172b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 14182b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim synchronized (mLock) { 14192b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim UserState userState = getUserStateLocked(mUserId); 14202b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim ServiceState serviceState = userState.serviceStateMap.get(mTvInputInfo.getId()); 14212b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (serviceState != null) { 14222b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mReconnecting = true; 14232b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mBound = false; 14242b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mService = null; 14252b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim serviceState.mCallback = null; 14262b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 14272b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim // Send null tokens for not finishing create session events. 14282b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim for (IBinder sessionToken : serviceState.mSessionTokens) { 14292b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim SessionState sessionState = userState.sessionStateMap.get(sessionToken); 14302b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim if (sessionState.mSession == null) { 14312b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim removeSessionStateLocked(sessionToken, sessionState.mUserId); 14322b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim sendSessionTokenToClientLocked(sessionState.mClient, 14335c80ad2077f3e755413ea47a35f51e9d25dbb083Jae Seo sessionState.mInputId, null, null, sessionState.mSeq); 14342b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 14352b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 14362b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim 1437969167dc05a6485a32d160895871cff46fd81884Wonsik Kim notifyStateChangedLocked(userState, mTvInputInfo.getId(), 1438969167dc05a6485a32d160895871cff46fd81884Wonsik Kim INPUT_STATE_DISCONNECTED, null); 14392b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim updateServiceConnectionLocked(mTvInputInfo.getId(), mUserId); 14402b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 14412b35a72a69f6fc39d21f7de9e21044d64db1380dSungsoo Lim } 14423957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14433957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14443957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 14453957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final class ServiceCallback extends ITvInputServiceCallback.Stub { 1446969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final String mInputId; 14473957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo private final int mUserId; 14483957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 1449969167dc05a6485a32d160895871cff46fd81884Wonsik Kim ServiceCallback(String inputId, int userId) { 1450969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mInputId = inputId; 14513957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo mUserId = userId; 14523957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14533957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo 14543957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo @Override 1455969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void onInputStateChanged(int state) { 14563957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo if (DEBUG) { 1457969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.d(TAG, "onInputStateChanged(inputId=" + mInputId + ", state=" 1458969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + state + ")"); 14593957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14603957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo synchronized (mLock) { 1461969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(mInputId, state, mUserId); 14623957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14633957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 14643957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo } 146531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 146631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private final class LogHandler extends Handler { 146731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_OPEN_ENTRY = 1; 146831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_UPDATE_ENTRY = 2; 146931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private static final int MSG_CLOSE_ENTRY = 3; 147031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 147131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public LogHandler(Looper looper) { 147231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo super(looper); 147331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 147431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 147531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo @Override 147631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo public void handleMessage(Message msg) { 147731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo switch (msg.what) { 147831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_OPEN_ENTRY: { 147931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 148031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 148131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 148231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 148331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 148431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 148531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 148631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 148731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_UPDATE_ENTRY: { 148831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 148931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 149031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long channelId = (long) args.arg2; 149131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg3; 149231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onUpdateEntry(uri, channelId, time); 149331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 149431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 149531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 149631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo case MSG_CLOSE_ENTRY: { 149731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = (SomeArgs) msg.obj; 149831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Uri uri = (Uri) args.arg1; 149931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long time = (long) args.arg2; 150031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onCloseEntry(uri, time); 150131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.recycle(); 150231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 150331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 150431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo default: { 15056a6059a29edf31e65541b3d8927a46f5846fb0a2Jae Seo Slog.w(TAG, "Unhandled message code: " + msg.what); 150631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 150731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 150831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 150931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 151031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 151131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onOpenEntry(Uri uri, long channelId, long watchStarttime) { 151231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 1513f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_TITLE, 1514f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, 1515f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, 1516bd23fa0ba1460a8d5194fd7c700030bf9c3f6fcbJae Seo TvContract.Programs.COLUMN_SHORT_DESCRIPTION 151731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 1518f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND " 1519f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND " 1520f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS + ">?"; 152131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] selectionArgs = { 152231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(channelId), 152331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime), 152431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String.valueOf(watchStarttime) 152531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 1526f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo String sortOrder = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + " ASC"; 152731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 152831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 152931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection, 153031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo selection, selectionArgs, sortOrder); 153131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 153231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1533f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, cursor.getString(0)); 1534f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 1535f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo cursor.getLong(1)); 153631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(2); 1537f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 1538f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, cursor.getString(3)); 153931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 154031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 154131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Schedule an update when the current program ends. 154231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo SomeArgs args = SomeArgs.obtain(); 154331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg1 = uri; 154431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg2 = channelId; 154531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo args.arg3 = endTime; 154631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args); 154731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo sendMessageDelayed(msg, endTime - System.currentTimeMillis()); 154831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 154931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 155031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 155131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 155231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 155331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 155431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 155531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 155631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onUpdateEntry(Uri uri, long channelId, long time) { 155731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String[] projection = { 1558f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 1559f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 1560f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_TITLE, 1561f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, 1562f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, 1563f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo TvContract.WatchedPrograms.COLUMN_DESCRIPTION 156431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo }; 156531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo Cursor cursor = null; 156631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo try { 156731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor = mContentResolver.query(uri, projection, null, null, null); 156831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null && cursor.moveToNext()) { 156931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchStartTime = cursor.getLong(0); 157031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long watchEndTime = cursor.getLong(1); 157131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String title = cursor.getString(2); 157231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long startTime = cursor.getLong(3); 157331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo long endTime = cursor.getLong(4); 157431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo String description = cursor.getString(5); 157531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 157631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Do nothing if the current log entry is already closed. 157731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (watchEndTime > 0) { 157831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo return; 157931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 158031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 158131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // The current program has just ended. Create a (complete) log entry off the 158231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // current entry. 158331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1584f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS, 158531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo watchStartTime); 1586f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, time); 1587f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_CHANNEL_ID, channelId); 1588f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_TITLE, title); 1589f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_START_TIME_UTC_MILLIS, startTime); 1590f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_END_TIME_UTC_MILLIS, endTime); 1591f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_DESCRIPTION, description); 159231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values); 159331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 159431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } finally { 159531dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo if (cursor != null) { 159631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo cursor.close(); 159731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 159831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 159931dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo // Re-open the current log entry with the next program information. 160031dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo onOpenEntry(uri, channelId, time); 160131dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 160231dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo 160331dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo private void onCloseEntry(Uri uri, long watchEndTime) { 160431dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo ContentValues values = new ContentValues(); 1605f5cd0b388ac31104e014f9193d06080851a09e18Jae Seo values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, watchEndTime); 160631dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo mContentResolver.update(uri, values, null, null); 160731dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 160831dc634be3610b062fbcc4afa02607ce8f4125f5Jae Seo } 1609969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 1610969167dc05a6485a32d160895871cff46fd81884Wonsik Kim final class Client { 1611969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void setState(String inputId, int state) { 1612969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 1613969167dc05a6485a32d160895871cff46fd81884Wonsik Kim setStateLocked(inputId, state, mCurrentUserId); 1614969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1615969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 1616969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 16173957091ba8f08c02b5e781098cb955a5f697a1ffJae Seo} 1618