TIF: Add TvInputManagerHostTest to test TvInputCallback#onInputUpdated

Bug: 27344945
Change-Id: I644dac13e23aafc475004bbb66aed5218b9ff71a
diff --git a/hostsidetests/tv/Android.mk b/hostsidetests/tv/Android.mk
new file mode 100644
index 0000000..bb5795b
--- /dev/null
+++ b/hostsidetests/tv/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := CtsHostsideTvTests
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt compatibility-host-util
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+
+LOCAL_CTS_TEST_PACKAGE := android.tv.hostsidetv
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/tv/AndroidTest.xml b/hostsidetests/tv/AndroidTest.xml
new file mode 100644
index 0000000..c3064eb
--- /dev/null
+++ b/hostsidetests/tv/AndroidTest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS tv host test cases">
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsHostsideTvTests.jar" />
+    </test>
+</configuration>
diff --git a/hostsidetests/tv/app/Android.mk b/hostsidetests/tv/app/Android.mk
new file mode 100644
index 0000000..3235244
--- /dev/null
+++ b/hostsidetests/tv/app/Android.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsHostsideTvInputApp
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/tv/app/AndroidManifest.xml b/hostsidetests/tv/app/AndroidManifest.xml
new file mode 100644
index 0000000..99eeb44
--- /dev/null
+++ b/hostsidetests/tv/app/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.tv.hostside">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <service android:name=".StubTvInputService"
+                 android:permission="android.permission.BIND_TV_INPUT">
+            <intent-filter>
+                <action android:name="android.media.tv.TvInputService"/>
+            </intent-filter>
+            <meta-data android:name="android.media.tv.input"
+                       android:resource="@xml/stub_tv_input_service" />
+        </service>
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.tv.hostside" />
+
+</manifest>
diff --git a/hostsidetests/tv/app/res/xml/stub_tv_input_service.xml b/hostsidetests/tv/app/res/xml/stub_tv_input_service.xml
new file mode 100644
index 0000000..bb9b0b7
--- /dev/null
+++ b/hostsidetests/tv/app/res/xml/stub_tv_input_service.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
+    android:setupActivity="com.android.cts.tv.hostside.StubSetupActivity" />
diff --git a/hostsidetests/tv/app/src/com/android/cts/tv/hostside/StubSetupActivity.java b/hostsidetests/tv/app/src/com/android/cts/tv/hostside/StubSetupActivity.java
new file mode 100644
index 0000000..761d56c
--- /dev/null
+++ b/hostsidetests/tv/app/src/com/android/cts/tv/hostside/StubSetupActivity.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tv.hostside;
+
+import android.preference.PreferenceActivity;
+
+public class StubSetupActivity extends PreferenceActivity {
+
+}
diff --git a/hostsidetests/tv/app/src/com/android/cts/tv/hostside/StubTvInputService.java b/hostsidetests/tv/app/src/com/android/cts/tv/hostside/StubTvInputService.java
new file mode 100644
index 0000000..4292747
--- /dev/null
+++ b/hostsidetests/tv/app/src/com/android/cts/tv/hostside/StubTvInputService.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tv.hostside;
+
+import android.content.Context;
+import android.media.tv.TvInputService;
+import android.net.Uri;
+import android.view.Surface;
+
+/**
+ * Stub implementation of (@link android.media.tv.TvInputService}.
+ */
+public class StubTvInputService extends TvInputService {
+    @Override
+    public Session onCreateSession(String inputId) {
+        return new StubSessionImpl(this);
+    }
+
+    private static class StubSessionImpl extends Session {
+        StubSessionImpl(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onRelease() {
+        }
+
+        @Override
+        public boolean onSetSurface(Surface surface) {
+            return false;
+        }
+
+        @Override
+        public void onSetStreamVolume(float volume) {
+        }
+
+        @Override
+        public boolean onTune(Uri channelUri) {
+            return false;
+        }
+
+        @Override
+        public void onSetCaptionEnabled(boolean enabled) {
+        }
+    }
+}
diff --git a/hostsidetests/tv/app2/Android.mk b/hostsidetests/tv/app2/Android.mk
new file mode 100644
index 0000000..a0dcab2
--- /dev/null
+++ b/hostsidetests/tv/app2/Android.mk
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsHostsideTvInputMonitor
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/tv/app2/AndroidManifest.xml b/hostsidetests/tv/app2/AndroidManifest.xml
new file mode 100644
index 0000000..0b20ee5
--- /dev/null
+++ b/hostsidetests/tv/app2/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.tv.hostside.app2">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="com.android.cts.tv.hostside.app2.TvViewMonitorActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.tv.hostside.app2" />
+
+</manifest>
diff --git a/hostsidetests/tv/app2/src/com/android/cts/tv/hostside/app2/TvViewMonitorActivity.java b/hostsidetests/tv/app2/src/com/android/cts/tv/hostside/app2/TvViewMonitorActivity.java
new file mode 100644
index 0000000..33d3a17
--- /dev/null
+++ b/hostsidetests/tv/app2/src/com/android/cts/tv/hostside/app2/TvViewMonitorActivity.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tv.hostside.app2;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.tv.TvInputManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+public class TvViewMonitorActivity extends Activity {
+    private static final String TAG = TvViewMonitorActivity.class.getSimpleName();
+    private static final String TEST_STRING = "HOST_SIDE_TEST_TV_INTPUT_IS_UPDATED";
+
+    private TvInputManager mManager;
+    private LoggingCallback mCallback = new LoggingCallback();
+
+    private boolean hasTvInputFramework() {
+        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LIVE_TV);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);
+        if (hasTvInputFramework()) {
+            mManager.registerCallback(mCallback, new Handler());
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (hasTvInputFramework()) {
+            mManager.unregisterCallback(mCallback);
+        }
+    }
+
+    private static class LoggingCallback extends TvInputManager.TvInputCallback {
+        @Override
+        public void onInputUpdated(String inputId) {
+            Log.i(TAG, TEST_STRING);
+        }
+    }
+}
diff --git a/hostsidetests/tv/src/com/android/cts/tv/TvInputManagerHostTest.java b/hostsidetests/tv/src/com/android/cts/tv/TvInputManagerHostTest.java
new file mode 100644
index 0000000..65a7928
--- /dev/null
+++ b/hostsidetests/tv/src/com/android/cts/tv/TvInputManagerHostTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tv;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.compatibility.common.util.VersionCodes;
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.FileNotFoundException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Scanner;
+
+public class TvInputManagerHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+    private static final String TEST_APK = "CtsHostsideTvInputApp.apk";
+    private static final String TEST_APK2 = "CtsHostsideTvInputMonitor.apk";
+    private static final String TEST_PKG = "com.android.cts.tv.hostside";
+    private static final String TEST_PKG2 = "com.android.cts.tv.hostside.app2";
+    private static final String CLASS = "TvViewMonitorActivity";
+    private static final String INPUT_UPDATED_STRING = "HOST_SIDE_TEST_TV_INTPUT_IS_UPDATED";
+    private static final String START_COMMAND = String.format(
+            "am start -W -a android.intent.action.MAIN -n %s/%s.%s", TEST_PKG2, TEST_PKG2, CLASS);
+    private static final String FEATURE_LIVE_TV = "android.software.live_tv";
+
+    private boolean mHasFeatureLiveTv;
+    private IAbi mAbi;
+    private IBuildInfo mCtsBuildInfo;
+    private HashSet<String> mAvailableFeatures;
+
+    private void installPackage(String apk) throws FileNotFoundException,
+            DeviceNotAvailableException {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuildInfo, apk), true));
+    }
+
+    private void uninstallPackage(String packageName, boolean shouldSucceed)
+            throws DeviceNotAvailableException {
+        final String result = getDevice().uninstallPackage(packageName);
+        if (shouldSucceed) {
+            assertNull("uninstallPackage(" + packageName + ") failed: " + result, result);
+        }
+    }
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuildInfo = buildInfo;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mAbi);
+        assertNotNull(mCtsBuildInfo);
+        mHasFeatureLiveTv = hasDeviceFeature(FEATURE_LIVE_TV);
+        if (mHasFeatureLiveTv) {
+            uninstallPackage(TEST_PKG, false);
+            uninstallPackage(TEST_PKG2, false);
+            installPackage(TEST_APK);
+            installPackage(TEST_APK2);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (mHasFeatureLiveTv) {
+            uninstallPackage(TEST_PKG, true);
+            uninstallPackage(TEST_PKG2, true);
+        }
+    }
+
+    public void testInputUpdated() throws Exception {
+        if (!mHasFeatureLiveTv) {
+            return;
+        }
+        ITestDevice device = getDevice();
+        device.executeAdbCommand("logcat", "-c");
+        device.executeShellCommand(START_COMMAND);
+        // Re-install the input app so the monitoring app can get the onInputUpdated callback.
+        installPackage(TEST_APK);
+        String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
+        String testString = "";
+        Scanner in = new Scanner(logs);
+        while (in.hasNextLine()) {
+            String line = in.nextLine();
+            if(line.contains(INPUT_UPDATED_STRING)) {
+                testString = line.split(":")[1].trim();
+            }
+        }
+        in.close();
+        assertEquals("Incorrect test string", INPUT_UPDATED_STRING, testString);
+    }
+
+    private boolean hasDeviceFeature(String requiredFeature) throws DeviceNotAvailableException {
+        if (mAvailableFeatures == null) {
+            // TODO: Move this logic to ITestDevice.
+            String command = "pm list features";
+            String commandOutput = getDevice().executeShellCommand(command);
+            CLog.i("Output for command " + command + ": " + commandOutput);
+
+            // Extract the id of the new user.
+            mAvailableFeatures = new HashSet<>();
+            for (String feature: commandOutput.split("\\s+")) {
+                // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
+                String[] tokens = feature.split(":");
+                assertTrue("\"" + feature + "\" expected to have format feature:{FEATURE_VALUE}",
+                        tokens.length > 1);
+                assertEquals(feature, "feature", tokens[0]);
+                mAvailableFeatures.add(tokens[1]);
+            }
+        }
+        boolean result = mAvailableFeatures.contains(requiredFeature);
+        if (!result) {
+            CLog.logAndDisplay(LogLevel.INFO, "Device doesn't have required feature "
+            + requiredFeature + ". Test won't run.");
+        }
+        return result;
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
index ccbcfee..3d04c0c 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
@@ -51,7 +51,7 @@
 
     private String mStubId;
     private TvInputManager mManager;
-    private LoggingCallback mCallabck = new LoggingCallback();
+    private LoggingCallback mCallback = new LoggingCallback();
 
     private static TvInputInfo getInfoForClassName(List<TvInputInfo> list, String name) {
         for (TvInputInfo info : list) {
@@ -139,8 +139,8 @@
             @Override
             public void run() {
                 try {
-                    mManager.registerCallback(mCallabck, new Handler());
-                    mManager.unregisterCallback(mCallabck);
+                    mManager.registerCallback(mCallback, new Handler());
+                    mManager.unregisterCallback(mCallback);
                 } catch (Exception e) {
                     fail();
                 }
@@ -156,13 +156,13 @@
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mManager.registerCallback(mCallabck, new Handler());
+                mManager.registerCallback(mCallback, new Handler());
             }
         });
         getInstrumentation().waitForIdleSync();
 
         // Test if onInputRemoved() is called.
-        mCallabck.resetLogs();
+        mCallback.resetLogs();
         PackageManager pm = getActivity().getPackageManager();
         ComponentName component = new ComponentName(getActivity(), StubTvInputService2.class);
         assertTrue(PackageManager.COMPONENT_ENABLED_STATE_DISABLED != pm.getComponentEnabledSetting(
@@ -172,12 +172,12 @@
         new PollingCheck(TIME_OUT_MS) {
             @Override
             protected boolean check() {
-                return mCallabck.isInputRemoved(mStubId);
+                return mCallback.isInputRemoved(mStubId);
             }
         }.run();
 
         // Test if onInputAdded() is called.
-        mCallabck.resetLogs();
+        mCallback.resetLogs();
         assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED, pm.getComponentEnabledSetting(
                 component));
         pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
@@ -185,14 +185,14 @@
         new PollingCheck(TIME_OUT_MS) {
             @Override
             protected boolean check() {
-                return mCallabck.isInputAdded(mStubId);
+                return mCallback.isInputAdded(mStubId);
             }
         }.run();
 
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mManager.unregisterCallback(mCallabck);
+                mManager.unregisterCallback(mCallback);
             }
         });
         getInstrumentation().waitForIdleSync();
@@ -205,12 +205,12 @@
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mManager.registerCallback(mCallabck, new Handler());
+                mManager.registerCallback(mCallback, new Handler());
             }
         });
         getInstrumentation().waitForIdleSync();
 
-        mCallabck.resetLogs();
+        mCallback.resetLogs();
         TvInputInfo defaultInfo = new TvInputInfo.Builder(getActivity(),
                 new ComponentName(getActivity(), StubTunerTvInputService.class)).build();
         TvInputInfo updatedInfo = new TvInputInfo.Builder(getActivity(),
@@ -221,7 +221,7 @@
         new PollingCheck(TIME_OUT_MS) {
             @Override
             protected boolean check() {
-                TvInputInfo info = mCallabck.getLastUpdatedTvInputInfo();
+                TvInputInfo info = mCallback.getLastUpdatedTvInputInfo();
                 return info !=  null && info.getTunerCount() == 10 && info.canRecord();
             }
         }.run();
@@ -230,7 +230,7 @@
         new PollingCheck(TIME_OUT_MS) {
             @Override
             protected boolean check() {
-                TvInputInfo info = mCallabck.getLastUpdatedTvInputInfo();
+                TvInputInfo info = mCallback.getLastUpdatedTvInputInfo();
                 return info !=  null && info.getTunerCount() == 1 && !info.canRecord();
             }
         }.run();
@@ -238,7 +238,7 @@
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mManager.unregisterCallback(mCallabck);
+                mManager.unregisterCallback(mCallback);
             }
         });
         getInstrumentation().waitForIdleSync();