Merge "TIF: remove test for READ_EPG which is deprecated in M" into mnc-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 8f07f5c..8e0d83d 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -128,6 +128,7 @@
     CtsAccessibilityServiceTestCases \
     CtsAccessibilityTestCases \
     CtsAdminTestCases \
+    CtsAlarmClockTestCases \
     CtsAnimationTestCases \
     CtsAppTestCases \
     CtsAppWidgetTestCases \
diff --git a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java b/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
index 286d4fd..f9daa3c 100644
--- a/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
+++ b/suite/cts/deviceTests/tvproviderperf/src/com/android/cts/tvproviderperf/TvProviderPerfTest.java
@@ -80,7 +80,7 @@
     @TimeoutReq(minutes = 8)
     public void testChannels() throws Exception {
         if (!mHasTvInputFramework) return;
-        double[] averages = new double[4];
+        double[] averages = new double[5];
 
         // Insert
         final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
@@ -138,23 +138,42 @@
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
         averages[1] = Stat.getAverage(applyBatchTimes);
 
-        // Query
+        // Query channels
         applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
             @Override
             public void run(int i) {
-                int j = 0;
                 try (Cursor cursor = mContentResolver.query(Channels.CONTENT_URI, null, null,
                         null, null)) {
                     while (cursor.moveToNext()) {
-                        ++j;
+                        // Do nothing. Just iterate all the items.
                     }
                 }
             }
         });
-        getReportLog().printArray("Elapsed time for query: ",
+        getReportLog().printArray("Elapsed time for query (channels): ",
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
         averages[2] = Stat.getAverage(applyBatchTimes);
 
+        // Query a channel
+        try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
+                projection, null, null, null)) {
+            final Uri channelUri = TvContract.buildChannelUri(cursor.getLong(0));
+            applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
+                @Override
+                public void run(int i) {
+                    assertTrue(cursor.moveToNext());
+                    try (Cursor c = mContentResolver.query(channelUri, null, null, null, null)) {
+                        while (c.moveToNext()) {
+                            // Do nothing. Just iterate all the items.
+                        }
+                    }
+                }
+            });
+        }
+        getReportLog().printArray("Elapsed time for query (a channel): ",
+                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+        averages[3] = Stat.getAverage(applyBatchTimes);
+
         // Delete
         applyBatchTimes = MeasureTime.measure(1, new MeasureRun() {
             @Override
@@ -164,16 +183,17 @@
         });
         getReportLog().printArray("Elapsed time for delete: ",
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
-        averages[3] = Stat.getAverage(applyBatchTimes);
+        averages[4] = Stat.getAverage(applyBatchTimes);
 
-        getReportLog().printArray("Average elapsed time for (insert, update, query, delete): ",
+        getReportLog().printArray("Average elapsed time for insert, update, query (channels), "
+                + "query (a channel), delete: ",
                 averages, ResultType.LOWER_BETTER, ResultUnit.MS);
     }
 
     @TimeoutReq(minutes = 12)
     public void testPrograms() throws Exception {
         if (!mHasTvInputFramework) return;
-        double[] averages = new double[6];
+        double[] averages = new double[7];
 
         // Prepare (insert channels)
         final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
@@ -262,20 +282,19 @@
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
         averages[1] = Stat.getAverage(applyBatchTimes);
 
-        // Query
+        // Query programs
         applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
             @Override
             public void run(int i) {
-                int j = 0;
                 try (Cursor cursor = mContentResolver.query(Programs.CONTENT_URI, null, null,
                         null, null)) {
                     while (cursor.moveToNext()) {
-                        ++j;
+                        // Do nothing. Just iterate all the items.
                     }
                 }
             }
         });
-        getReportLog().printArray("Elapsed time for query: ",
+        getReportLog().printArray("Elapsed time for query (programs): ",
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
         averages[2] = Stat.getAverage(applyBatchTimes);
 
@@ -284,22 +303,41 @@
             @Override
             public void run(int i) {
                 Uri channelUri = channelUris.get(i);
-                int j = 0;
                 try (Cursor cursor = mContentResolver.query(
                         TvContract.buildProgramsUriForChannel(
                                 channelUri, 0,
                                 PROGRAM_DURATION_MS * TRANSACTION_SIZE / 2),
                         null, null, null, null)) {
                     while (cursor.moveToNext()) {
-                        ++j;
+                        // Do nothing. Just iterate all the items.
                     }
                 }
             }
         });
-        getReportLog().printArray("Elapsed time for query with selection: ",
+        getReportLog().printArray("Elapsed time for query (programs with selection): ",
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
         averages[3] = Stat.getAverage(applyBatchTimes);
 
+        // Query a program
+        try (final Cursor cursor = mContentResolver.query(Programs.CONTENT_URI,
+                projection, null, null, null)) {
+            final Uri programUri = TvContract.buildProgramUri(cursor.getLong(0));
+            applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
+                @Override
+                public void run(int i) {
+                    assertTrue(cursor.moveToNext());
+                    try (Cursor c = mContentResolver.query(programUri, null, null, null, null)) {
+                        while (c.moveToNext()) {
+                            // Do nothing. Just iterate all the items.
+                        }
+                    }
+                }
+            });
+        }
+        getReportLog().printArray("Elapsed time for query (a program): ",
+                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+        averages[4] = Stat.getAverage(applyBatchTimes);
+
         // Delete programs
         applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
             @Override
@@ -315,7 +353,7 @@
         });
         getReportLog().printArray("Elapsed time for delete programs: ",
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
-        averages[4] = Stat.getAverage(applyBatchTimes);
+        averages[5] = Stat.getAverage(applyBatchTimes);
 
         // Delete channels
         applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
@@ -327,10 +365,11 @@
         });
         getReportLog().printArray("Elapsed time for delete channels: ",
                 applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
-        averages[5] = Stat.getAverage(applyBatchTimes);
+        averages[6] = Stat.getAverage(applyBatchTimes);
 
-        getReportLog().printArray("Average elapsed time for (insert, update, query, "
-                + "query with selection, delete channels, delete programs): ",
+        getReportLog().printArray("Average elapsed time for insert, update, query (programs), "
+                + "query (programs with selection), query (a channel), delete (channels), "
+                + "delete (programs): ",
                 averages, ResultType.LOWER_BETTER, ResultUnit.MS);
     }
 }
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index c477128..479f72a 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -174,5 +174,22 @@
     "android.hardware.camera2.cts.SurfaceViewPreviewTest#testPreparePerformance"
   ],
   bug: 17989532
+},
+{
+  description: "The new AE/AF trigger tests are not yet passing on all devices",
+  names: [
+    "android.hardware.camera2.cts.RobustnessTest#testBasicTriggerSequence",
+    "android.hardware.camera2.cts.RobustnessTest#testSimultaneousTriggers",
+    "android.hardware.camera2.cts.RobustnessTest#testAfThenAeTrigger",
+    "android.hardware.camera2.cts.RobustnessTest#testAeThenAfTrigger"
+  ],
+  bug: 22180706
+},
+{
+  description: "The new create session test is not yet passing on all devices",
+  names: [
+    "android.hardware.camera2.cts.CameraDeviceTest#testCreateSessions"
+  ],
+  bug: 22092756
 }
 ]
diff --git a/tests/tests/alarmclock/Android.mk b/tests/tests/alarmclock/Android.mk
new file mode 100644
index 0000000..c99f953
--- /dev/null
+++ b/tests/tests/alarmclock/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2015 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)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsAlarmClockTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/alarmclock/AndroidManifest.xml b/tests/tests/alarmclock/AndroidManifest.xml
new file mode 100644
index 0000000..88bb91d
--- /dev/null
+++ b/tests/tests/alarmclock/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<!--
+ * Copyright (C) 2015 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="android.alarmclock.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="TestActivity"
+            android:label="The Target Activity for alarmClock Intents Test">
+            <intent-filter>
+                <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.alarmclock.cts"
+                     android:label="CTS tests of android.alarmclock">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
+
diff --git a/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockIntentsTest.java b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockIntentsTest.java
new file mode 100644
index 0000000..33ac546
--- /dev/null
+++ b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockIntentsTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 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 android.alarmclock.cts;
+
+import android.app.AlarmManager;
+import android.app.AlarmManager.AlarmClockInfo;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.provider.AlarmClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.util.Calendar;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class AlarmClockIntentsTest extends ActivityInstrumentationTestCase2<TestActivity> {
+    static final String TAG = "AlarmClockIntentsTest";
+    static final int ALARM_TEST_WINDOW_MINS = 2;
+    private static final int TIMEOUT_MS = 20 * 1000;
+
+    private TestActivity mActivity;
+    private AlarmManager mAlarmManager;
+    private NextAlarmReceiver mReceiver = new NextAlarmReceiver();
+    private final CountDownLatch mLatch = new CountDownLatch(1);
+    private Context mContext;
+
+    public AlarmClockIntentsTest() {
+      super(TestActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+        mActivity = getActivity();
+        mAlarmManager = (AlarmManager) mActivity.getSystemService(Context.ALARM_SERVICE);
+        IntentFilter filter = new IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
+        filter.addAction(AlarmClock.ACTION_SET_ALARM);
+        mContext.registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mContext.unregisterReceiver(mReceiver);
+        super.tearDown();
+    }
+
+    public void testSetAlarm() throws Exception {
+        // set an alarm for ALARM_TEST_WINDOW millisec from now.
+        // Assume the next alarm is NOT within the next ALARM_TEST_WINDOW millisec
+        // TODO: fix this assumption
+        AlarmTime expected = getAlarmTime();
+
+        // set the alarm
+        assertNotNull(mActivity);
+        assertTrue(mActivity.setAlarm(expected));
+
+        // wait for the alarm to be set
+        if (!mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+            fail("Failed to receive broadcast in " + (TIMEOUT_MS / 1000) + "sec");
+        }
+
+        // verify the next alarm
+        assertTrue(isNextAlarmSameAs(expected));
+    }
+
+    public void testDismissAlarm() throws Exception {
+        assertTrue(mActivity.cancelAlarm(getAlarmTime()));
+    }
+
+    public void testSnoozeAlarm() throws Exception {
+        assertTrue(mActivity.snoozeAlarm());
+    }
+
+    private AlarmTime getAlarmTime() {
+        Calendar now = Calendar.getInstance();
+        now.add(Calendar.MINUTE, ALARM_TEST_WINDOW_MINS);
+        long nextAlarmTime = now.getTimeInMillis();
+        return new AlarmTime(nextAlarmTime);
+    }
+
+    private boolean isNextAlarmSameAs(AlarmTime expected) {
+        AlarmClockInfo alarmInfo = mAlarmManager.getNextAlarmClock();
+        if (alarmInfo == null) {
+            return false;
+        }
+        AlarmTime next = new AlarmTime(alarmInfo.getTriggerTime());
+        if (expected.mIsPm != next.mIsPm ||
+            expected.mHour != next.mHour ||
+            expected.mMinute != next.mMinute) {
+          Log.i(TAG, "Next Alarm time is not same expected time: " +
+              "next = " + next + ", expected = " + expected);
+          return false;
+        }
+        return true;
+    }
+
+    class NextAlarmReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
+                Log.i(TAG, "received broadcast");
+                mLatch.countDown();
+            }
+        }
+    }
+
+    static class AlarmTime {
+      int mHour;
+      int mMinute;
+      boolean mIsPm;
+
+      AlarmTime(long l) {
+          Calendar cal = Calendar.getInstance();
+          cal.setTimeInMillis(l);
+          mHour = cal.get(Calendar.HOUR);
+          mMinute = cal.get(Calendar.MINUTE);
+          mIsPm = cal.get(Calendar.AM_PM) == 1;
+          Log.i(TAG, "Calendar converted is: " + cal);
+      }
+
+      AlarmTime(int hour, int minute, boolean isPM) {
+          mHour = hour;
+          mMinute = minute;
+          mIsPm = isPM;
+      }
+
+      @Override
+      public String toString() {
+          String isPmString = (mIsPm) ? "pm" : "am";
+          return  mHour + ":" + mMinute + isPmString;
+      }
+    }
+}
diff --git a/tests/tests/alarmclock/src/android/alarmclock/cts/TestActivity.java b/tests/tests/alarmclock/src/android/alarmclock/cts/TestActivity.java
new file mode 100644
index 0000000..9ec33ae
--- /dev/null
+++ b/tests/tests/alarmclock/src/android/alarmclock/cts/TestActivity.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 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 android.alarmclock.cts;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.AlarmClock;
+import android.util.Log;
+
+import java.util.Calendar;
+
+public class TestActivity extends Activity {
+    static final String TAG = "TestActivity";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, " in onCreate");
+    }
+
+    private void setParams(int hour, int minute, boolean isPM, Intent intent) {
+        intent.putExtra(AlarmClock.EXTRA_ALARM_SEARCH_MODE, AlarmClock.ALARM_SEARCH_MODE_TIME);
+        intent.putExtra(AlarmClock.EXTRA_IS_PM, isPM);
+        intent.putExtra(AlarmClock.EXTRA_HOUR, hour);
+        intent.putExtra(AlarmClock.EXTRA_MINUTES, minute);
+    }
+
+    private boolean start(Intent intent) {
+        try {
+            startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Log.wtf(TAG, e);
+            return false;
+        }
+        return true;
+    }
+
+    public boolean cancelAlarm(AlarmClockIntentsTest.AlarmTime time) {
+        Intent intent = new Intent(AlarmClock.ACTION_DISMISS_ALARM);
+        setParams(time.mHour, time.mMinute, time.mIsPm, intent);
+        Log.i(TAG, "sending DISMISS_ALARM intent for: " + time + ", Intent = " + intent);
+        return start(intent);
+    }
+
+    public boolean setAlarm(AlarmClockIntentsTest.AlarmTime time) {
+        Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM);
+        int hour = time.mHour;
+        if (time.mIsPm) {
+          hour += 12;
+        }
+        setParams(hour, time.mMinute, time.mIsPm, intent);
+        Log.i(TAG, "Setting alarm: " + hour + ":" + time.mMinute + ", Intent = " + intent);
+        return start(intent);
+    }
+
+    public boolean snoozeAlarm() {
+        Intent intent = new Intent(AlarmClock.ACTION_SNOOZE_ALARM);
+        Log.i(TAG, "sending SNOOZE_ALARM intent." + intent);
+        return start(intent);
+  }
+}